So I'm trying to send an e-mail from Excel with Python. Right now I just have all the e-mails set up in column A1 separated by semicolons. If I put the e-mails into Python directly, they send out but when I use the Python call-out, it freaks out giving me this error. How exactly can I make this work?
import smtplib
from email.mime.image import MIMEImage
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
import pandas
from datetime import datetime
server = smtplib.SMTP('relay.xxx.com')
email_df = pandas.read_excel(f"E-mails.xlsx", sheet_name="Emails", nrows=1, usecols = "A")
sender = '[email protected]'
receivers = 'Email'
receivers = list(email_df)
print(receivers)
msg = MIMEMultipart('related')
msg['Subject'] = 'Test mail'
msg['From'] = sender
with smtplib.SMTP('relay.xxx.com') as server:
msg['To'] = receivers
server.sendmail(sender, receivers, bytes(msg.as_string()))
print(f"Successfully sent email to: {receivers}")
I don't want multiple e-mails to be sent out. I want 1 single e-mail with a bunch of e-mails in the address box.
Alternatively, if there's a way can read it by column, (addr1 in a1, addr in a2) that'd also be better.
Appreciate it.
CodePudding user response:
If you can get your email addresses (from your df) into a list in the desired format, e.g.:
print(receivers)
['[email protected]', '[email protected]', '[email protected]']
then you can add this after its assignment to turn it into a string for send_mail (as it requires a string instead of a list):
receivers = ", ".join(receivers)
You mention that it would be ideal if you had an email address per row under column A in your spreadsheet. So if you can get your Excel spreadsheet into this format (with a column heading of "Email") then you can do this to get the aforementioned list:
email_df = pandas.read_excel(f"E-mails.xlsx", sheet_name="Emails", usecols = "A")
receivers = email_df['Email'].tolist()
So, for completeness (with Excel spreadsheet in its new format of one email address per row under column A), your code would change to:
import smtplib
from email.mime.image import MIMEImage
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
import pandas
from datetime import datetime
server = smtplib.SMTP('relay.xxx.com')
email_df = pandas.read_excel(f"E-mails.xlsx", sheet_name="Emails")
receivers = email_df['Email'].tolist()
print(receivers) # Check list is one valid email address per element
receivers = ", ".join(receivers)
sender = '[email protected]'
msg = MIMEMultipart('related')
msg['Subject'] = 'Test mail'
msg['From'] = sender
with smtplib.SMTP('relay.xxx.com') as server:
msg['To'] = receivers
server.sendmail(sender, receivers, bytes(msg.as_string(), encoding='utf-8'))
print(f"Successfully sent email to: {receivers}")
CodePudding user response:
If you build a message, you'd better use the send_message
interface. And I would suggest to use the newer EmailMessage
interface which is cleaner and simpler that the older MimeMultipart
one:
import smtplib
from email.message import EmailMessage
...
msg = EmailMessage()
msg['Subject'] = 'Test mail'
msg['From'] = sender
msg.set_payload('Message text.\nLine 2...')
# or eventually add parts with msg.add_related(...), msg.add_alternative(..)
# or msg.add_attachment(...)
with smtplib.SMTP('relay.xxx.com') as server:
msg['To'] = receivers
server.send_messages(msg)
print(f"Successfully sent email to: {receivers}")