1

My aim for this program is to send multiple e-mail addresses a message along with a PDF file attached to the e-mail. How would I do that? I have two Traceback calls(Shown after the code). So far the code works when there is no attachments being sent but as I try to send an attachment everything seems to fall apart. Thanks

EDIT: I believe I have to use these two lines of code somewhere.
message.attach(part)
text = message.as_string()

Although when I write them down it says Unresolved attribute reference 'attach' for class 'str'

from email.mime.base import MIMEBase
import pandas as pd
import smtplib, ssl

subject = "An email with attachment from Python"
sender_email = input("Enter your E-mail Address: ")
password = input("Enter your password: ")

email_list = pd.read_excel("D:\Learning Python\Mini_Projects\emailaddresses.xlsx", engine="openpyxl")
# Read Excel Spreadsheet
names = email_list['Name']
receiver_email = email_list['Email']

message = """Subject: Training Program! 💪 
Hi {names}, I hope you received this e-mail with the attachment"""
filename = "TrainingProgram.pdf"

with open(filename, "rb") as attachment:
    part = MIMEBase("application", "octet-stream")
    part.set_payload(attachment.read())

encoders.encode_base64(part)

part.add_header(
    "Content-Disposition",
    f"attachment; filename= {filename}",
)
context = ssl.create_default_context()
with  smtplib.SMTP("smtp.gmail.com", 587) as server:
    server.starttls(context=context)
    server.login(sender_email, password)
    for i in range(len(receiver_email)):
        name = names[i]
        email = receiver_email[i]
        server.sendmail(sender_email, receiver_email, message)
    print("E-mails Sent!")



File "D:/Learning Python/Mini_Projects/main.py", line 117, in <module>
    server.sendmail(sender_email, [email], message)
  File "C:\Users\janss\AppData\Local\Programs\Python\Python38\lib\smtplib.py", line 859, in sendmail
    msg = _fix_eols(msg).encode('ascii')
UnicodeEncodeError: 'ascii' codec can't encode character '\U0001f4aa' in position 27: ordinal not in range(128)

1 Answer 1

1

ASCII encoding does not support emojis. Remove the 💪 in the email body, and it should work. If you absolutely want to keep the emoji, you would have to use a MIMEText object, see this question for an example.

EDIT: Why aren't you using the name and email variables in the for loop ? The current code sends an email to an adress being a list, I wonder why it's not erroring there ...

    for i in range(len(receiver_email)):
        name = names[i]
        email = receiver_email[i]
        server.sendmail(sender_email, receiver_email, message)

Maybe you meant your for loop like the following ?

    for email in receiver_email:
        server.sendmail(sender_email, email, message)

Additionally, your message will be sent as you coded it, instead of with the names filled in. For this, you need to put an f in front of the string. I think the message should be like this:

message = f"""Subject: Training Program!
Hi {", ".join(names)}, I hope you received this e-mail with the attachment"""

EDIT2:

Unresolved attribute reference 'attach' for class 'str'

This is because str has no method attach, only email.mime.multipart.MIMEMultipart has. See this answer on how to correctly send attachments.

Sign up to request clarification or add additional context in comments.

3 Comments

Thanks, that seemed to fix the errors. My only issue now is that the attachment is not being sent a long with the e-mail. So I'm getting an empty e-mail with just the subject, body but no PDF files
@Johnlewis "I'm getting an empty e-mail with just the subject, body but no PDF files" - no wonder - you are loading the attachment PDF into your script, but never telling smptlib to send it along with your email ! And please re-read my post, I edited it because I found two more issues in your code which though aren't related to the PDF not being sent.
Thanks for your assistance, much appreciated! I'll look more into it as I'm still a bit confused to as how I'll go about doing it.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.