this is probably a trivial question but I couldn't find an answer anywhere.
I need to write a script that receives an entire MIME message in a string, as such:
From: Jerry Peek <jerry#ora.com>
To: mh-users#ics.uci.edu
Subject: New edition of "MH & xmh" covers MIME and MH-E
MIME-Version: 1.0
Content-Type: multipart/alternative; boundary="----- =_aaaaaaaaaa0"
Content-ID: <1283.780402430.1#ora.com>
------- =_aaaaaaaaaa0
Content-Type: text/plain; charset="us-ascii"
Content-ID: <1283.780402430.2#ora.com>
We've just released the new third edition of "MH & xmh: Email for
Users & Programmers." Changes include:
- MIME (Multimedia) mail
- The popular MH-E GNU Emacs front-end to MH
...omitted...
------- =_aaaaaaaaaa0--
and passes it on to an SMTP server.
I saw alot of examples that force me to parse the message and fetch the to, from and
message data. is there a method that allows me to send the string as is?
thanks
It might exists, but I do not think so. For the SMTP protocol (RFC 2821 - Simple Mail Transfer Protocol), you have 4 different elements : the SMTP server to which to connect, the MAIL-FROM enveloppe email address, the RCPT-TO destination address(es) and the DATA. All the headers are included in the DATA in SMTP sense.
So when using smtplib you have either to give a text message, a from address and one or more recipient addresses, or a parsed Message to allow smtplib to find from address and recipients in the headers. That's the reason why I think the short answer to you question is no.
Related
When I send mail with header like this message['Reply-To'] = '' (Python), it work fine on localhost. When I click Reply in Outlook at that received mail, To field is empty. When I send the same mail from production via company SMTP server, the mail also contains empty Reply-To header, however If I click Reply in Outlook, the address from that the mail had been received is prefilled in To field.
Is there a bug in company SMTP or why does it work only in localhost?
Thank you.
In Reply-To empty, Outlook would default to the sender address. IMHO that is how it is supposed to work.
Having a weird problem with emails I am sending out via Python email / smtplib.
I am attempting to compose an email with:
Alternatives of plain-text and HTML message bodies
An image embedded inline in the HTML body
A separate non-inline attachment
The MIME structure is setup like this:
multipart/mixed
multipart/alternative
text/plain
multipart/related
text/html
image/png - inline
application/pdf - attachment
This seems to work fine on every mail client I've tested {BlueMail on Android, iOS mail client, Roundcube} except for the Windows 10 mail client. For some reason, the Windows 10 built-in mail client seems to show the inline image just fine, but shows no trace of the other attachment.
The limited information I have been able to find on the internet points to this being a bug with the Windows 10 mail client, but I have personally received other emails in this client with both inline and attached attachments, which are displayed just fine - so there obviously is some sort of workaround / alternative message structure that works.
My question is thus: How can I format this message differently so that it will show up properly in all relevant mail clients?
I am composing the email like this, in Python:
message = MIMEMultipart("mixed")
message["From"] = ...
.
.
.
bodyText = "..."
bodyHTML = "..."
mailFrom = "..."
targetEmail = "..."
imageContent = ...
messageBody = MIMEMultipart("alternative")
messageBody.attach(MIMEText(bodyText, "plain"))
messageBodyHTML = MIMEMultipart("related")
messageBodyHTML.attach(MIMEText(bodyHTML, "html"))
messageImage = MIMEImage(imageContent)
messageImage.add_header("Content-Disposition", 'inline; filename="..."')
messageImage.add_header("Content-ID", "<id used in html body>")
messageBodyHTML.attach(messageImage)
messageBody.attach(messageBodyHTML)
message.attach(messageBody)
attachment = MIMEApplication(fileContent, Name=fileName)
attachment.add_header("Content-Disposition", 'attachment; filename="..."')
message.attach(attachment)
self.smtplibSession.sendmail(mailSource, targetEmail, message.as_string())
Update: Here's the message data from Windows 10 mail (as output via the "save" feature - there's no way to view the original message raw data that I can find...)
MIME-Version: 1.0
Date: Thu, 30 May 2019 17:45:28 +0200
From: xxxxx <xxxxx>
Subject: xxxxx
Thread-Topic: xxxxx
To: "xxxxx" <xxxxx>
Content-Type: multipart/related;
boundary="_5D6C043C-FD42-42F9-B0E0-841DBFBA96D5_"
--_5D6C043C-FD42-42F9-B0E0-841DBFBA96D5_
Content-Transfer-Encoding: quoted-printable
Content-Type: text/html; charset="utf-8"
<center><img src=3D"cid:embedded-image" alt=...
--_5D6C043C-FD42-42F9-B0E0-841DBFBA96D5_
Content-Type: image/png; name="embedded-image.png"
Content-ID: <embedded-image>
Content-Transfer-Encoding: base64
Content-Disposition: inline; filename="embedded-image.png"
iVBORw0KGgoAAAAN...
--_5D6C043C-FD42-42F9-B0E0-841DBFBA96D5_--
I'm not sure if this is a result of saving the email from the app, or this is what the app is actually storing, but it seems that the Windows 10 Mail app is cutting out everything outside the multipart/related stanza - that is, it's only taking the chosen alternative and not storing anything else.
For comparison, I've found and exported an email that displayed properly, with an image, html, and attachment, but the format seems to be a lot simpler - that email consisted only of a multipart/mixed layer with text/html and an application/pdf attachment. That email used an external image referenced in the HTML, instead of embedding it in the message - I would like to avoid hosting the images in each email externally.
Unlike you, there was no problem with the attachment file, instead I've had problems in displaying inline images (Windows 10 Mail 16005.11629.20174.0).
Unfortunately, handling non-standard approaches in MIME messages correctly is a feature that is expected to have good email clients. Apparently Windows 10 Mail is not as "good" yet.
The structure I recommend you to use is:
multipart/mixed
├─── multipart/related
│ ├─── multipart/alternative
│ │ ├─── text/plain
│ │ └─── text/html
│ └─── image/png - inline image
└─── application/pdf - attachment
I've had no problems with this structure in the following clients.
Windows 10 Mail
Gmail Web & Android
Outlook Web & Android & Windows Desktop
Blue Mail Android
Roundcube Web
MailEnable Web
So, give the following code a try to see if it works for you.
message = MIMEMultipart("mixed")
message["From"] = ...
.
.
.
bodyText = "..."
bodyHTML = "..."
mailFrom = "..."
targetEmail = "..."
imageContent = ...
fileContent = ...
relatedBody = MIMEMultipart("related")
messageBody = MIMEMultipart("alternative")
messageBody.attach(MIMEText(bodyText, "plain"))
messageBody.attach(MIMEText(bodyHTML, "html"))
relatedBody.attach(messageBody)
messageImage = MIMEImage(imageContent)
messageImage.add_header("Content-Disposition", 'inline; filename="..."')
messageImage.add_header("Content-ID", "<id used in html body>")
relatedBody.attach(messageImage)
message.attach(relatedBody)
attachment = MIMEApplication(fileContent)
attachment.add_header("Content-Disposition", 'attachment; filename="..."')
message.attach(attachment)
Hi I've just found out that I can't use smtplib to send emails from GAE, but I need to specify custom mime-types as in:
part = MIMEBase('application', "vnd.openxmlformats-officedocument.wordprocessingml.document")
part.set_payload( doc )
Encoders.encode_base64(part)
part.add_header('Content-Disposition', 'attachment; filename="%s"' % "ackReceived.docx")
msg.attach(part)
If I try to use the api in the documented way it sends the attachment with 'application/msword' which is causing my docx to corrupt.
Can I specify the mime-type manually using google's mail api?
Edit: A little more about the problem I face when my docx is sent by mail api:
smtplib sends the attachment like this:
Content-Type: application/vnd.openxmlformats-officedocument.wordprocessingml.document
MIME-Version: 1.0
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename="ackReceived.docx"
UEsDBBQABgAIAAAAIQCCVgdJnwEAAMgIAAATAAAAW0NvbnRlbnRfVHlwZXNdLnhtbMWWS0/DMBCE
70j8h8hXlLhwQAg17YHHEZAo4mzsTWMRP2Qvj/571k1bIaiaiDbiEilZz3wzsSJnPP00TfYOIWpn
S3ZajFgGVjql7bxkT7Pb/IJlEYVVonEWSraAyKaT46PxbOEhZqS2sWQ1or/kPMoajIiF82BpUrlg...
Google mail api sends the same file like this:
Content-Type: application/msword
MIME-Version: 1.0
Content-Disposition: attachment; filename="ackReceived.docx"
PK�����!�‚VIŸ��È�����[Content_Types].xmlÅ–KOÃ0„ïHü‡ÈW”¸p#5íÇ(âlìMc?d/þ{ÖM[!¨šˆ6â)YÏ|3±"g<ý4Mö!jgKvZŒXV:¥í¼dO³Ûü‚e…U¢qJ¶€È¦“ã£ñlá!f¤¶±d5¢¿ä<ÊŒˆ…ó`iR¹`Òm˜s/䫘?ιtÁbŽÉƒMÆ×P‰·³›OzÜ&!9Ë®Úu U2á}£¥#ó4å[uÞÎè´IÜô|»"#w ÞúÑ'_u)H¹\kíãÉ*Ó=½Ì d"à0dÇ?\P\9ùfQ쮶…çªJKØè“›NBŒ´K¦)6#´íÌqÑ#<|ŠÖ·'þYc}SU ±Oó¤-~i»i€Hñ†¨»rîŒð/ƒ¥øfÞ¤rÃ!ö~cݬ(ÃÚ¹3B
BA8=|‚Ö¸'ÿìßøi³éß÷äп7Ÿxâ¥!¬¬;C ”Ð^÷߉¥Í.$|ÎG:yÃj¯¼¤Î©°‡€z÷—¶!’õÞý Ö...
In short, you can't specify custom mime types using Google AppEngine e-mail.
In order to send e-mail via Google AppEngine through Google you need to use the Mail API provided. You can see why .docx is using the content type application/msword here: https://cloud.google.com/appengine/docs/standard/python/mail/mail-with-headers-attachments. You might want to submit an issue to the issue tracker in order to resolve this.
It may be worth looking at 3rd party e-mail providers such as Amazon's SES or SendGrid. I've personally been using Amazon's SES to get around a lot of the lack of features and restrictions in GAE's Mail API (though Google is constantly improving this API).
You can use the boto library to communicate with AWS SES and send RAW e-mail messages. (Look at this question for an example on how to create the e-mail, small modifications may be needed for your purposes)
I'm using email.Message class and gnupg library to:
1 - parse email string fetched from Twisted imap4 client.
2 - get the attached file, a .pgp
3 - decrypt it.
I can decrypt typical mail content, as:
-----BEGIN PGP MESSAGE-----
Version: PGP 9
(...)
-----END PGP MESSAGE-----
but the attachment affair is really making my life a hell.
Well, I tried a lot of different ways, but the most logical should be this:
message = email.message_from_string(content)
if message.is_multipart():
attachment = message.get_payload(1)
gpg = gnupg.GPG(gnupghome=settings.PGP_PATH)
return gpg.decrypt_file(attachment.get_payload(), passphrase=settings.PGP_PASSPH)
The attachment var first lines are:
From nobody Mon Oct 15 18:54:12 2012
Content-type: application/octet-stream;
name="No_Norm_AMLT_908_1210201201.txt.pgp"
Content-Disposition: attachment; filename="No_Norm_AMLT_908_1210201201.txt.pgp"
Content-Transfer-Encoding: base64
And then all the encrypted stuff.
Anyway... it's really strange, there's something I don't get. If I download the attachment from a normal mail client software (i.e. Thunderbird) I get a .pgp file that seems binary (strange characters appears if I edit it with a plain text editor) and I can decrypt it using the bash command:
gpg --decrypt No_Norm_AMLT_908_1210201201.txt.pgp
I don't know how to get the same result (the file decrypted) using email.Message class and gnupg, I tried to save the payload of the attachment to a file, and this is different from the downloaded from Thunderbird one, I can't decrypt it, I tried also to put it into a StringIO, and also encoding it with base64.
The message I get from gpg is:
[GNUPG:] NODATA 1
[GNUPG:] NODATA 2
gpg: decrypt_message failed: eof
Thank you!
Ok solved! I had to:
base64.decodestring(attachment.get_payload())
then decrypt it using gpg, and worked. This can be figured out because of the header:
Content-Transfer-Encoding: base64
The final code is:
message = email.message_from_string(content)
if message.is_multipart():
attachment = message.get_payload(1)
gpg = gnupg.GPG(gnupghome=settings.PGP_PATH)
return gpg.decrypt_file(base64.decodestring(attachment.get_payload()),
passphrase=settings.PGP_PASSPH)
I have a test.html file that I want to send via email(I am refering about the page content). Is there a way for getting the information from the html and sending it as a email? If you have any other ideas please share.
Here's a quick and dirty script I just wrote which might be what you're looking for.
https://gist.github.com/1790847
"""
this is a quick and dirty script to send HTML email - emphasis on dirty :)
python emailpage.py http://www.sente.cc
made to answer: http://stackoverflow.com/questions/9226719/sending-a-html-file-via-python
Stuart Powers
"""
import lxml.html
import smtplib
import sys
import os
page = sys.argv[1] #the webpage to send
root = lxml.html.parse(page).getroot()
root.make_links_absolute()
content = lxml.html.tostring(root)
message = """From: Stuart Powers <stuart.powers#gmail.com>
To: Stuart Powers <stuart.powers#gmail.com>
MIME-Version: 1.0
Content-type: text/html
Subject: %s
%s""" %(page, content)
smtpserver = smtplib.SMTP("smtp.gmail.com",587)
smtpserver.starttls()
smtpserver.login("stuart.powers#gmail.com",os.environ["GPASS"])
smtpserver.sendmail('stuart.powers#gmail.com', ['stuart.powers#gmail.com'], message)
There are many ways of reading files in python and there are also ways to send emails in python. Why don't you look up the documentation and come back with some coding error ?
Sending emails in python: http://docs.python.org/library/email-examples.html
Reading files in python: http://docs.python.org/tutorial/inputoutput.html