Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sending an email via the Python email library throws error "expected string or bytes-like object"

I am trying to send a csv file as an attachment via a simple function in python 3.6.

from email.message import Message
from email.mime.base import MIMEBase
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText

def email():


    msg = MIMEMultipart()
    msg['Subject'] = 'test'
    msg['From'] = '[email protected]'
    msg['To'] = '[email protected]'
    msg.preamble = 'preamble'

    with open("test.csv") as fp:
        record = MIMEText(fp.read())
        msg.attach(record)

    server = smtplib.SMTP('smtp.gmail.com', 587)
    server.ehlo()
    server.starttls()
    server.login("[email protected]", "password")
    server.sendmail("[email protected]", "[email protected]", msg)
    server.quit()

Calling email() produces the error expected string or bytes-like object. Redefining server.sendmail("[email protected]", "[email protected]", msg) as server.sendmail("[email protected]", "[email protected]", msg.as_string()) causes an email to be sent, but sends the csv file in the body of the email, NOT as an attachment. can anyone give me some pointers on how to send the csv file as an attachment?

like image 914
MeesterTeem Avatar asked Jan 04 '17 17:01

MeesterTeem


People also ask

How do you fix expected string or bytes like an object?

The Python "TypeError: expected string or bytes-like object" occurs when we pass an argument of a different type to a method that expects a string argument, e.g. re. sub() . To solve the error, make sure to pass a string argument to the method.

What is email library in Python?

The email package is a library for managing email messages. It is specifically not designed to do any sending of email messages to SMTP (RFC 2821), NNTP, or other servers; those are functions of modules such as smtplib and nntplib .


1 Answers

1) You should use msg.as_string() if you call smtplib.SMTP.sendmail(). Alternatively, if you have Python 3.2 or newer, you can use server.send_message(msg).

2) You should add a body to your message. By design no one ever sees the preamble.

3) You should use content-disposition: attachment to indicate which parts are attachments and which are inline.

Try this:

def email():


    msg = MIMEMultipart()
    msg['Subject'] = 'test'
    msg['From'] = 'XXX'
    msg['To'] = 'XXX'
    msg.preamble = 'preamble'

    body = MIMEText("This is the body of the message")
    msg.attach(body)

    with open("test.csv") as fp:
        record = MIMEText(fp.read())
        record['Content-Disposition'] = 'attachment; filename="test.csv"'
        msg.attach(record)

    server = smtplib.SMTP('smtp.gmail.com', 587)
    server.ehlo()
    server.starttls()
    server.login("XXX", "XXX")
    server.sendmail("XXX", "XXX", msg.as_string())
    server.quit()
like image 158
Robᵩ Avatar answered Sep 21 '22 22:09

Robᵩ