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'] = 'test@gmail.com'
    msg['To'] = 'testee@gmail.com'
    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("test@gmail.com", "password")
    server.sendmail("test@gmail.com", "testee@gmail.com", msg)
    server.quit()

Calling email() produces the error expected string or bytes-like object. Redefining server.sendmail("test@gmail.com", "testee@gmail.com", msg) as server.sendmail("atest@gmail.com", "testee@gmail.com", 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?


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()


 MORE:


 ? Sitecore custom MTA for localhost
 ? Sending automated email on database update using AWS
 ? Can Anyone Help me out: Automation Testing of an email Notification using Selenium WebDriver Java
 ? Rails SendGrid Email From Development Environment
 ? Mailgun: '550 Requested action not taken error' when sending to certain domains
 ? ASP.NET C# - Sending Email from Gmail/Yahoo Live SMTP Server not working
 ? SMTP VBA : When Sending Mail - Transport Failed to Connect to server
 ? Getting a warning message after opening email using PHP
 ? IMAP Access to BCC field
 ? Append retrieving more than requested 13 bytes