Sending an email using sockets. I want to separate plain text and attachment. I use MIME multipart/mixed; boundary.
cSockSSL.send("MIME-Version: 1.0\r\n".encode())
cSockSSL.send("Content-Type: multipart/mixed; boundary=gg4g5gg\r\n".encode())
cSockSSL.send("--gg4g5gg".encode('ascii'))
cSockSSL.send("Content-Type: text/plain\r\n".encode())
cSockSSL.send("Some text".encode())
cSockSSL.send("--gg4g5gg".encode())
cSockSSL.send("Content-Type: text/plain\r\n".encode())
cSockSSL.send("Content-Disposition: attachment; filename = gg.txt\r\n".encode())
cSockSSL.send(txt_file)
cSockSSL.send("--gg4g5gg--".encode())
cSockSSL.send("\r\n.\r\n".encode())
In this case, I get an empty email with the header. If I delete first boundary I'll get this:
Some text--gg4g5ggContent-Type: text/plain Content-Disposition: attachment; filename = gg.txt Hey! I'm txt file!--gg4g5gg--
How to correctly split content-type?
CodePudding user response:
Your email data is malformed, as you are missing several required line breaks.
Per RFC 2822, you need to separate the email's headers from the email's body using \r\n\r\n
instead of \r\n
.
And per RFC 2045, you need to separate MIME headers from MIME bodies using \r\n\r\n
instead of \r\n
. And, you are missing \r\n
in front of each MIME boundary that follows a text body, and after each MIME boundary.
So, essentially, you are sending an email that looks like this, all squished together:
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary=gg4g5gg
--gg4g5ggContent-Type: text/plain
Some text--gg4g5ggContent-Type: text/plain
Content-Disposition: attachment; filename = gg.txt
<txt_file>--gg4g5gg--
.
But it needs to look more like this instead:
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary=gg4g5gg
--gg4g5gg
Content-Type: text/plain
Some text
--gg4g5gg
Content-Type: text/plain
Content-Disposition: attachment; filename = gg.txt
<txt_file>
--gg4g5gg--
.
So, try this instead:
cSockSSL.send("DATA\r\n".encode())
# verify response is 354...
cSockSSL.send("MIME-Version: 1.0\r\n".encode())
cSockSSL.send("Content-Type: multipart/mixed; boundary=gg4g5gg\r\n".encode())
cSockSSL.send("\r\n".encode()) # add a line break
cSockSSL.send("--gg4g5gg\r\n".encode('ascii')) # add a line break
cSockSSL.send("Content-Type: text/plain\r\n".encode())
cSockSSL.send("\r\n".encode()) # add a line break
cSockSSL.send("Some text".encode())
cSockSSL.send("\r\n--gg4g5gg\r\n".encode()) # add line breaks
cSockSSL.send("Content-Type: text/plain\r\n".encode())
cSockSSL.send("Content-Disposition: attachment; filename=gg.txt\r\n".encode())
cSockSSL.send("\r\n".encode()) # add a line break
cSockSSL.send(txt_file)
cSockSSL.send("\r\n--gg4g5gg--\r\n".encode()) # add line breaks
cSockSSL.send(".\r\n".encode())
Something else to be aware of - because the DATA
command terminator is .\r\n
, if "Some text"
or txt_file
contain any lines that begin with the .
character, you MUST escape each leading .
as ..
, per RFC 2821 Section 4.5.2.
I suggest you study the RFCs mentioned above more carefully.