كيف يمكنني الرد على رسالة بريد إلكتروني باستخدام Python Imaplib وتضمين الرسالة الأصلية؟
سؤال
أنا أستخدم حاليًا imaplib
لجلب رسائل البريد الإلكتروني من خادم ومعالجة المحتويات والمرفقات.
أرغب في الرد على الرسائل برسالة حالة/خطأ وروابط إلى المحتوى الناتج الذي تم إنشاؤه على موقعي إذا كان يمكن معالجتها. يجب أن يشمل ذلك الرسالة الأصلية ولكن يجب أن تسقط أي مرفقات (والتي ستكون كبيرة) ويفضل استبدالها بأسماء الملفات/الأحجام الخاصة بها فقط.
نظرًا لأنني أمشي بالفعل أجزاء رسائل MIME ، أفترض أن ما أحتاج إلى القيام به هو إنشاء شجرة رسالة MIME جديدة تحتوي على نسخة من الرسالة الأصلية وحذف/استبدال عقد المرفقات.
قبل أن أبدأ في هذا المسار ، كنت آمل أن يتمكن شخص ما من إعطائي بعض النصائح. هل هناك أي نوع من وظيفة المكتبة للقيام بذلك؟ أي نوع من السلوك القياسي الذي يجب أن ألتزم به؟
أنا أعرف حاليا/أنا باستخدام imaplib
, smtplib
و email
الوحدات النمطية ولكن ربما فقدت شيئًا واضحًا هناك. هذا يعمل في Django أيضًا ، لذلك يمكن استخدام أي شيء فيه django.core.email
إذا كان ذلك يجعل الأمر أسهل.
المحلول
هيكل شجرة MIME الأصلي للرسالة الواردة كما يلي (باستخدام email.iterators._structure(msg)
):
multipart/mixed
text/html (message)
application/octet-stream (attachment 1)
application/octet-stream (attachment 2)
يؤدي الرد عبر Gmail إلى الهيكل التالي:
multipart/alternative
text/plain
text/html
أي أنها ليست ذكية كما اعتقدت ، فقط تجاهل المرفقات (جيدة) وتوفير إصدارات النص و HTML التي تعيد هيكلة بشكل صريح "المحتوى المقتبس".
بدأت أعتقد أن هذا كل ما يجب علي فعله أيضًا ، ما عليك سوى الرد برسالة بسيطة كما بعد التخلص من المرفقات ، لا توجد نقطة كبيرة في الاحتفاظ بالرسالة الأصلية.
ومع ذلك ، قد تجيب أيضًا على سؤالي الأصلي منذ أن اكتشفت كيفية ذلك الآن على أي حال.
أولاً ، استبدل جميع المرفقات في الرسالة الأصلية بالنص/العناصر النائبة النصية:
import email
original = email.message_from_string( ... )
for part in original.walk():
if (part.get('Content-Disposition')
and part.get('Content-Disposition').startswith("attachment")):
part.set_type("text/plain")
part.set_payload("Attachment removed: %s (%s, %d bytes)"
%(part.get_filename(),
part.get_content_type(),
len(part.get_payload(decode=True))))
del part["Content-Disposition"]
del part["Content-Transfer-Encoding"]
ثم قم بإنشاء رسالة رد:
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.message import MIMEMessage
new = MIMEMultipart("mixed")
body = MIMEMultipart("alternative")
body.attach( MIMEText("reply body text", "plain") )
body.attach( MIMEText("<html>reply body text</html>", "html") )
new.attach(body)
new["Message-ID"] = email.utils.make_msgid()
new["In-Reply-To"] = original["Message-ID"]
new["References"] = original["Message-ID"]
new["Subject"] = "Re: "+original["Subject"]
new["To"] = original["Reply-To"] or original["From"]
new["From"] = "me@mysite.com"
ثم قم بإرفاق كائن رسالة MIME الأصلي وأرسل:
new.attach( MIMEMessage(original) )
s = smtplib.SMTP()
s.sendmail("me@mysite.com", [new["To"]], new.as_string())
s.quit()
الهيكل الناتج هو:
multipart/mixed
multipart/alternative
text/plain
text/html
message/rfc822
multipart/mixed
text/html
text/plain
text/plain
أو أنه أبسط قليلاً باستخدام Django:
from django.core.mail import EmailMultiAlternatives
from email.mime.message import MIMEMessage
new = EmailMultiAlternatives("Re: "+original["Subject"],
"reply body text",
"me@mysite.com", # from
[original["Reply-To"] or original["From"]], # to
headers = {'Reply-To': "me@mysite.com",
"In-Reply-To": original["Message-ID"],
"References": original["Message-ID"]})
new.attach_alternative("<html>reply body text</html>", "text/html")
new.attach( MIMEMessage(original) ) # attach original message
new.send()
تنتهي النتيجة (في Gmail على الأقل) التي تُظهر الرسالة الأصلية على أنها "---- رسالة تم إعادة توجيهها ----" هذا ليس ما كنت عليه تمامًا ، لكن الفكرة العامة تعمل وآمل أن تساعد هذه الإجابة شخصًا يحاول ذلك اكتشف كيفية التعادلات مع رسائل MIME.