Search code examples
pythonemail-attachments

Sending single email with 3 different attachments python 3


I'm just looking to send an email with 3 csv file attachments. When i get it to run, trying a solution i found on here, it gives me a BIN file instead of the 3 files. Or, trying another solution, it will only send the last of the the 3 files. When i run the code below, its gives me TypeError: add.header() takes 3 positional arguments but 4 were given.

I understand that it can be done with a function, but i'm not sure how to have it pull all three files into it. I've spent numerous hours trying to figure it out.

Posting it on here is my last resort. I appreciate any help in finding a solution.

import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.base import MIMEBase
from email import encoders
import time
import os

msg = MIMEMultipart()
msg['From'] = EMAIL_FROM
msg['To'] = ", ".join(RECIPIENT_LIST)
msg['Subject'] = 'Louisiana Contractors List'

#email content
message = """<html>
<body>
Attached is the Louisiana Contractors Spreadsheet.
<br><br>

Let me know if you have any questions

</body>
</html>
"""

msg.attach(MIMEText(message, 'html'))

files = [
    'C:/Users/rkrouse/Downloads/search-results.csv',
    'C:/Users/rkrouse/Downloads/search-results(1).csv',
    'C:/Users/rkrouse/Downloads/search-results(2).csv']

for a_file in files:
    attachment = open(a_file, 'rb')
    part = MIMEBase('application','octet-stream')
    part.set_payload((attachment).read())
    part.add_header('Content-Disposition', 'attachment', a_file = os.path.basename('C:/Users/rkrouse/Downloads/search-results.csv'))
    encoders.encode_base64(part)
    msg.attach(part)

for a_file in files:
    attachment = open(a_file, 'rb')
    part = MIMEBase('application','octet-stream')
    part.set_payload((attachment).read())
    part.add_header('Content-Disposition', 'attachment', a_file = os.path.basename('C:/Users/rkrouse/Downloads/search-results(1).csv'))
    encoders.encode_base64(part)
    msg.attach(part)

for a_file in files:
    attachment = open(a_file, 'rb')
    part = MIMEBase('application','octet-stream')
    part.set_payload(attachment.read())
    part.add_header('Content-Disposition', 'attachment', a_file = os.path.basename('C:/Users/rkrouse/Downloads/search-results(2).csv'))
    encoders.encode_base64(part)
    msg.attach(part)

#sends email
smtpserver = smtplib.SMTP(EMAIL_SERVER, EMAIL_PORT)
smtpserver.sendmail(EMAIL_FROM, RECIPIENT_LIST, msg.as_string())
smtpserver.quit()

Solution

  • Updated tested solution:

    import smtplib
    from email.mime.multipart import MIMEMultipart
    from email.mime.text import MIMEText
    from email.mime.base import MIMEBase
    from email import encoders
    import time
    import os
    
    msg = MIMEMultipart()
    msg['From'] = EMAIL_FROM
    msg['To'] = ", ".join(RECIPIENT_LIST)
    msg['Subject'] = 'Louisiana Contractors List'
    
    #email content
    message = """<html>
    <body>
    Attached is the Louisiana Contractors Spreadsheet.
    <br><br>
    
    Let me know if you have any questions
    
    </body>
    </html>
    """
    
    msg.attach(MIMEText(message, 'html'))
    
    files = [
        'C:/Users/rkrouse/Downloads/search-results.csv',
        'C:/Users/rkrouse/Downloads/search-results(1).csv',
        'C:/Users/rkrouse/Downloads/search-results(2).csv']
    
    for a_file in files:
        attachment = open(a_file, 'rb')
        file_name = os.path.basename(a_file)
        part = MIMEBase('application','octet-stream')
        part.set_payload(attachment.read())
        part.add_header('Content-Disposition',
                        'attachment',
                        filename=file_name)
        encoders.encode_base64(part)
        msg.attach(part)
    
    #sends email
    
    smtpserver = smtplib.SMTP(EMAIL_SERVER, EMAIL_PORT)
    smtpserver.sendmail(EMAIL_FROM, RECIPIENT_LIST, msg.as_string())
    smtpserver.quit()
    

    As you can see you need to specify the filename in the base64 encoding. Also you are iterating the files three time.

    A for loop is used to go through a list, set, array, etc. One for loop (as all attachments are in one list) should be enough.