简体   繁体   中英

How to email unique attachments to multiple unique recipients using Python?

I am writing an automation Python Script. My intention is to email multiple unique attachments to multiple unique recipients. For example l have 1000 unique statements that must be emailed to 1000 unique clients. I want my Python script to be able to pick an attachment automatically and send it to the right recipient!

I have created the script and that creates the pdf attachments and name them after each email address of recipients so that l can use the names to pick the attachment and match that with the email of the recipient. It Picks attachment perfectly BUT the problems it keeps incrementing attachment to users in each iteration..

 #1.READING FILE NAMES WHICH ARE EMAIL ADDRESS FOR RECEPIENTS
 import os, fnmatch
 filePath = "C:/Users/DAdmin/Pictures/"

def readFiles(path):

fileNames =fnmatch.filter(os.listdir(path), '*.pdf')
i=0
pdfFilesNamesOnly=[]
while i < len(fileNames):
    s =fileNames[i]
    removeThePdfExtension= s[0:-4]
    pdfFilesNamesOnly.append(removeThePdfExtension)
    i+=1

return pdfFilesNamesOnly
-----------------------------------------------------------
#2.SENDING AN EMAIL WITH UNIQUE ATTACHMENT TO MULTIPLE UNIQUE RECEPIENTS 

import smtplib
import mimetypes
from optparse import OptionParser
from email.mime.multipart import MIMEMultipart
from email import encoders
from email.mime.text import MIMEText
from email.mime.base import MIMEBase
from email.mime.application import MIMEApplication
import os,fnmatch
from readFileNames import readFiles

filePath = "C:/Users/DAdmin/Pictures/"

listOfEmails= readFiles(filePath)# Files are named after emails 

def sendEmails(listOfFiNames): #sends the email

    email = 'goddietshe@gmail.com' # Your email
    password = '#####' # Your email account password

    send_to_list = listOfEmails# From the file names

#creating a multipart object
    subject ="MONTHLY STATEMENTS"
    mg = MIMEMultipart('alternative')
    mg['From'] = email
    mg['To'] = ",".join(send_to_list)
    mg['Subject'] = subject
    mg.attach(MIMEText("Please receive your monthly statement",'plain'))

   # Attaching a file now before emailing. (Where l have a problem)

    for i in listOfEmails:
       if i in send_to_list: 
            newFile = (i+'.pdf') # create the name of   the attachment to email using the name(which is the email) and will be used to pick the attachment

            with open(newFile,'rb') as attachment:
                part = MIMEBase('application','x- pdf')
                part.set_payload(attachment.read())
                attachment.close()
            encoders.encode_base64(part)
            part.add_header('Content- Disposition','attachment; filename="%s"' % newFile )

            mg.attach(part)
            text =mg.as_string() # converting the  message obj to a string/text obj

            server = smtplib.SMTP('smtp.gmail.com', 587)        # Connect to the server
            server.starttls() # Use TLS

            server.login(email, password) # Login to the email server

            # this is where it is emailing stuff
            server.sendmail(email, i , text) # Send the email
            server.quit() # Logout of the email server
            print("The mail was sent")


    #print("Failed ")

sendEmails(listOfFiNames)

I expect it to email each unique attachment to each unique recipient who are 1000 automatically

You reuse mg (message), using only attach , so your attachments pile up. You need to substitute the whole previous content with new content using set_payload because there is no "remove" method.

In doing this, you have to remember to re-add the text which you set before the loop:

mg.attach(MIMEText("Please receive your monthly statement",'plain'))
for i in listOfEmails:

because by using set_payload you lose all previous parts you attached. I'd just save this as a variable and then add it in the loop.

Moreover:

mg['To'] = ",".join(send_to_list)

This line makes all messages send to all people. You need to move this part to the loop as well, setting only one email address at once.


EDIT Applying those changes:

def sendEmails(): #sends the email

    email = 'goddietshe@gmail.com' # Your email
    password = '#####' # Your email account password

    #creating a multipart object
    subject ="MONTHLY STATEMENTS"
    mg = MIMEMultipart('alternative')
    mg['From'] = email
    # mg['To'] = ",".join(listOfEmails) # NO!
    mg['Subject'] = subject

    text_content = MIMEText("Please receive your monthly statement",'plain')) #safe it for later, rather than attach it - we'll have to re-attach it every loop run

    for i in listOfEmails:
       if i in send_to_list: 
            newFile = (i+'.pdf') # create the name of   the attachment to email using the name(which is the email) and will be used to pick the attachment

            with open(newFile,'rb') as attachment:
                part = MIMEBase('application','x- pdf')
                part.set_payload(attachment.read())
                attachment.close()
            encoders.encode_base64(part)
            part.add_header('Content- Disposition','attachment; filename="%s"' % newFile )

            mg.set_payload(text_content) #change the whole content into text only (==remove previous attachment)
            mg.attach(part) #keep this - new attachment
            mg["To"] = i # send the email to the current recipient only!
            text =mg.as_string() # converting the  message obj to a string/text obj

            server = smtplib.SMTP('smtp.gmail.com', 587)        # Connect to the server
            server.starttls() # Use TLS

            server.login(email, password) # Login to the email server

            # this is where it is emailing stuff
            server.sendmail(email, i , text) # Send the email
            server.quit() # Logout of the email server
            print("The mail was sent")

 **Works very fine like this. Thanks @h4z3**

 def sendEmail():
    email = 'goddietshetu@gmail.com' # Your email
    password = '####' # Your email account password
    subject ="MONTHLY STATEMENTS"

    #creating a multipart object
    mg = MIMEMultipart('alternative')
    mg['From'] = email
    mg['Subject'] = subject

    # attaching a file now


    listOfEmails = readFileNames(filePath)
for i in listOfEmails:
    attachment  =open(i+'.pdf','rb')

    part = MIMEBase('application','octet-stream')
    part.set_payload(attachment.read())
    encoders.encode_base64(part)
    part.add_header('Content-Disposition',f"attachment; filename=  {i}.pdf")

    mg.set_payload(mg.attach(MIMEText("",'plain')))
    mg.attach(MIMEText("Please receive your monthly statement",'plain'))
    mg.attach(part)
    mg['To'] = i


    text =mg.as_string() # converting the message obj to a string/text obj

    server = smtplib.SMTP('smtp.gmail.com', 587) # Connect to the server
    server.starttls() # Use TLS
    server.login(email, password) # Login to the email server
    server.sendmail(email, i , text) # Send the email
server.quit() # Logout of the email serv
print("The mail was sent")
sendEmail()

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM