LINUX.ORG.RU

парсинг /var/mail/user с помощью mailbox

 , ,


0

1

Есть файл с письмами в /var/mail/user, парсить это все пытаюсь с помощью модуля https://pymotw.com/3/mailbox/, все гуд, но как вытащить сам body и аттачи? Что то совсем не доганяю

★★★

Последнее исправление: noname_user (всего исправлений: 2)

Модуль email старательно не замечаем?

anonymous
()
Ответ на: комментарий от anonymous

Так, тут вроде как все ок, но такая проблема

from email.parser import BytesParser, Parser
from email.policy import default


with open('/var/mail/mailbot', 'rb') as fp:
	headers = BytesParser(policy=default).parse(fp)

	print('To: {}'.format(headers['to']))
	print('From: {}'.format(headers['from']))
	print('Subject: {}'.format(headers['subject']))
собственно в /var/mail/mailbot около 5 писем, но выводит только 1, я слегка не догоняю почему, да и текст самого письма как спарсить то ?

noname_user ★★★
() автор топика

Может быть я что то не так делаю? Потому что я надеялся что письма будут как отдельные файлы, а не все в одном. Где я туплю?

noname_user ★★★
() автор топика
Последнее исправление: noname_user (всего исправлений: 1)
Ответ на: комментарий от noname_user

Сначала парсишь mailbox на отдельные сообщения с помощью mailbox, потом отдельные сообщения парсишь с помощью email.

anonymous
()
Ответ на: комментарий от anonymous
from email.parser import BytesParser, Parser
from email.policy import default
import mailbox

for message in mailbox.mbox('/var/mail/mailbot'):
	headers = Parser(policy=default).parsestr(message)

	#  Now the header items can be accessed as a dictionary:
	print('To: {}'.format(headers['to']))
	print('From: {}'.format(headers['from']))
	print('Subject: {}'.format(headers['subject']))

	# You can also access the parts of the addresses:
	print('Recipient username: {}'.format(headers['to'].addresses[0].username))
	print('Sender name: {}'.format(headers['from'].addresses[0].display_name))

Вылазит эксепт:

TypeError: initial_value must be str or None, not mboxMessage

UPDATE:
Решил так: str(message)
Осталасб проблема с получением body письма, собственно каким образом ?

noname_user ★★★
() автор топика
Последнее исправление: noname_user (всего исправлений: 2)
Ответ на: комментарий от noname_user

Получил тело:

bodytext=message.get_payload()[0];
Всем спасибо

noname_user ★★★
() автор топика

собственно выложу, что получилось, код мб и не очень, но другим думаю поможет:

# -*- coding: utf-8 -*-

from email.parser import BytesParser, Parser
from email.policy import default
import mailbox
import MySQLdb as mdb
import quopri
import string
import uuid
import base64
import re
import time

con = mdb.connect('localhost', '', '', '', use_unicode=True, charset="utf8");

def encoded_words_to_text(encoded_words):
	encoded_word_regex = r'=\?{1}(.+)\?{1}([B|Q])\?{1}(.+)\?{1}='
	try:
		charset, encoding, encoded_text = re.match(encoded_word_regex, encoded_words).groups()
	except Exception as e:
		return None
	if encoding is 'B':
		byte_string = base64.b64decode(encoded_text)
	elif encoding is 'Q':
		byte_string = quopri.decodestring(encoded_text)
	return byte_string.decode(charset)

with con:
	for message in mailbox.mbox('/var/mail/mailbot'):
		attachs = list()
		headers = Parser(policy=default).parsestr(str(message))
		if message.is_multipart():
			# get body mail
			for body in message.get_payload():
				if body.get_content_type() == 'text/plain':
					bodytext = quopri.decodestring(str(message.get_payload()[1].get_payload())).decode('utf8')
				if body.get_content_type() == 'multipart/alternative':
					for body2 in body.get_payload():
						bodytext = quopri.decodestring(str(body2.get_payload())).decode('utf8')
					
		for part in message.walk():
			if part.get_content_maintype() == 'multipart': continue
			# if part.get_content_maintype() == 'text': continue
			if part.get('Content-Disposition') == 'inline': continue
			if part.get('Content-Disposition') is None: continue

			filename = part.get_filename()
			if filename != None:
				if not encoded_words_to_text(filename):
					filename=filename
				else :
					filename=encoded_words_to_text(filename)
			filename=str(uuid.uuid1())+'|'+filename
			open('/home/admin/web/***/public_html/attach/'+filename, 'wb').write(part.get_payload(decode=True))
			attachs.append(filename)

		cur = con.cursor()
		cur.execute("select id from mails where mailid = %s",(headers['Message-Id'],))
		mail = rows = cur.fetchone()
		if(mail == None):
			timestamp = int(time.time())
			cur.execute('INSERT INTO mails(`mailid`, `subject`, `to`, `from`, `body`, `time_receive`) VALUES(%s, %s, %s, %s, %s, %s)',(headers['Message-ID'], headers['subject'].encode('utf-8'), headers['to'], headers['from'], bodytext, timestamp))
			mailid = cur.lastrowid
		for at in attachs:
				cur.execute('INSERT INTO attach(`mailid`, `name`) VALUES(%s, %s)', (mailid, at))

noname_user ★★★
() автор топика
Последнее исправление: noname_user (всего исправлений: 1)
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.