22

Okay, I know there is a few questions out there addressing this, but I cannot find a way to make it work properly. I would assume it is as simple as the below code, but this does not attach my file. Any help would be greatly appreciated. I am also very new to Python. Is there a mail module that I should be importing to make the function work?

import smtplib
fromaddr = "example@example.com
toaddrs = "reciever@example.com

msg = "help I cannot send an attachment to save my life"
attach = ("csvonDesktp.csv")

username = user
password = password

server = smtplib.SMTP('smtp.gmail.com:587')
server.starttls()
server.login(username,password)
server.sendmail(fromaddr, toaddrs, msg, attach)
server.quit()
ubuntuuber
  • 740
  • 1
  • 7
  • 18

2 Answers2

88

Send a multipart email with the appropriate MIME types.

https://docs.python.org/2/library/email-examples.html

So possible something like this (I tested this):

import smtplib
import mimetypes
from email.mime.multipart import MIMEMultipart
from email import encoders
from email.message import Message
from email.mime.audio import MIMEAudio
from email.mime.base import MIMEBase
from email.mime.image import MIMEImage
from email.mime.text import MIMEText

emailfrom = "sender@example.com"
emailto = "destination@example.com"
fileToSend = "hi.csv"
username = "user"
password = "password"

msg = MIMEMultipart()
msg["From"] = emailfrom
msg["To"] = emailto
msg["Subject"] = "help I cannot send an attachment to save my life"
msg.preamble = "help I cannot send an attachment to save my life"

ctype, encoding = mimetypes.guess_type(fileToSend)
if ctype is None or encoding is not None:
    ctype = "application/octet-stream"

maintype, subtype = ctype.split("/", 1)

if maintype == "text":
    fp = open(fileToSend)
    # Note: we should handle calculating the charset
    attachment = MIMEText(fp.read(), _subtype=subtype)
    fp.close()
elif maintype == "image":
    fp = open(fileToSend, "rb")
    attachment = MIMEImage(fp.read(), _subtype=subtype)
    fp.close()
elif maintype == "audio":
    fp = open(fileToSend, "rb")
    attachment = MIMEAudio(fp.read(), _subtype=subtype)
    fp.close()
else:
    fp = open(fileToSend, "rb")
    attachment = MIMEBase(maintype, subtype)
    attachment.set_payload(fp.read())
    fp.close()
    encoders.encode_base64(attachment)
attachment.add_header("Content-Disposition", "attachment", filename=fileToSend)
msg.attach(attachment)

server = smtplib.SMTP("smtp.gmail.com:587")
server.starttls()
server.login(username,password)
server.sendmail(emailfrom, emailto, msg.as_string())
server.quit()
MuffintopBikini
  • 1,042
  • 7
  • 11
  • Excellent sample. I like how you made it generic and using the libraries to get the mimetypes rather than hard-coding it. – Varun Verma Jun 06 '17 at 22:40
  • 1
    Hey the text body is not coming through – Vishnu Kiran Mar 19 '18 at 01:00
  • 2
    It would have been better if it was properly commented, although it is pretty explanatory, it's not apparent for a beginner like me what function is used for which purpose or why.. Any way, a comprehensive solution. – Gsbansal10 Dec 30 '18 at 13:14
  • python 3.8 server.send_message(msg) https://docs.python.org/3/library/smtplib.html – AJ AJ Aug 24 '20 at 08:54
  • I'm following the above method but my csv attachment is attached in a .msg file in the email I have received. How can I send only the csv without encoded in another .msg file? – user3782604 Jun 09 '21 at 04:49
6

There is a complete example in the Python documentation. I can copy and paste the relevant parts here but the whole page is not very long so it's better if you go and have a look at it there.

s16h
  • 4,647
  • 1
  • 21
  • 33