whla
whla

Reputation: 811

Attaching file in Python email

So I have tried multiple method in attaching a file (in particular a CSV file) to an email in python and sending. I have had text email working correctly and I indeed receive a CSV file, just an empty one. I am currently sending my attachments like so:

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

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

# organizing receivers
receiver = receivers.split(',')

# creating subject
subject = 'BLAH BLAH'
timestamp = time.strftime("%m/%d/%Y:%H:%M:%S")
subject += str(timestamp)

# form email
msg = MIMEMultipart()
msg['From'] = sender
msg['To'] = " ".join(receivers)
msg['Subject'] = subject
msg['Message-Id'] = make_msgid()
msg['Date'] = formatdate(localtime=True)
msg.attach(MIMEText(msgstr, 'plain'))

if maintype == "text":
    fp = open("results.csv")
    attachment = MIMEText(fp.read(), _subtype=subtype)
    fp.close()

else:
    fp = open('results.csv', "rb")
    attachment = MIMEBase(maintype, subtype)
    attachment.set_payload(fp.read())
    fp.close()
    encoders.encode_base64(attachment)

attachment.add_header("Content-Disposition", "attachment", filename='results.csv')
msg.attach(attachment)

try:
    smtpobj = smtplib.SMTP('smtp.gmail.com:587')
    smtpobj.ehlo()
    smtpobj.starttls()
    smtpobj.ehlo()
    smtpobj.login(username, password)

    smtpobj.sendmail(sender, receiver, msg.as_string())
    smtpobj.quit()

except smtplib.SMTPException:
    print 'Error: unable to send mail'

This is similar to the answer here: python can't send attachment files through email I have also tried simpler approaches similar to: How to send email attachments with Python https://docs.python.org/2/library/email.html

and others, but with no success. How can I send a complete attachment?

Upvotes: 2

Views: 1920

Answers (2)

Dr Manhattan
Dr Manhattan

Reputation: 14097

Try edit this section as so

else:
    with open('results.csv', "rb") as fp:
        fp.seek(0)
        attachment = MIMEBase(maintype, subtype)
        attachment.set_payload(fp.read())
        encoders.encode_base64(attachment)

Upvotes: 1

whla
whla

Reputation: 811

So after much debugging I realized that I hadn't properly closed the file before trying to read it again for the composition of the email. I had code similar to below:

with open('results.csv', "rb") as csvfile:
    #compose the csv file
    #blah
    #blah
    #blah
    #then I called my email function but the file hadn't yet been closed and I was trying to reopen.

To fix this I just simply called my email function outside of the with statement to close the file.

with open('results.csv', "rb") as csvfile:
        #compose the csv file
        #blah
        #blah
        #blah

send_the_email()

I hope this prevents others from wasting as much time as I did, on something so simple.

Upvotes: 2

Related Questions