Send individual emails to multiple recipients - python

I have put together a code to send emails to multiple recipients. However each recipient receives all mails instead of his own.
Dataframe:
email content
mark#gmail.com Hi Mark, bla bla
eve#gmail.com Hi Eve, bla bla
john#gmail.com Hi, John bla bla
for content in df['content']:
for email in df['email']:
message = MIMEMultipart()
message['Subject'] = "Subject"
message['From'] = 'my email'
message['Reply-to'] = 'my email'
message['To'] = '{}'.format(email)
text = MIMEText(mail)
message.attach(text)
server = smtplib.SMTP ('smtp.gmail.com',587)
server.ehlo()
server.starttls()
server.login(login, password)
server.sendmail(message['From'], message['To'], message.as_string())
server.quit()

Try this:
df = {
'content': ['test1', 'test2', 'test3'],
'email': ['mail1#mail.com', 'mail2#mail.com', 'mail3#mail.com']
}
x = 0
for email in df['email']:
print(email)
print(df["content"][x]+"\n")
x+=1

Just zip columns together and omit one loop:
for email, content in zip(df['email'], df['content']):
message = MIMEMultipart()
message['Subject'] = "Subject"
message['From'] = 'my email'
message['Reply-to'] = 'my email'
message['To'] = '{}'.format(email)
text = MIMEText(mail)
message.attach(text)
server = smtplib.SMTP ('smtp.gmail.com',587)
server.ehlo()
server.starttls()
server.login(login, password)
server.sendmail(message['From'], message['To'], message.as_string())
server.quit()

I was iterating it twice. Instead of using 2 for loops, the correct way to iterate through out DataFrame is using
Instead of this:
for content in df['content']:
for email in df['email']:
Use this:
for c in df.itertuples():
message = MIMEMultipart()
message['To'] = '{}'.format(c[0])
text = MIMEText(c[1])
message.attach(text)

Related

I can't send a message from telegram to mail

When entering a message , the console outputs that the "ms" variable is empty , how can this be fixed ?
def send_mail(id_user, message_topic):
data = read_date_json()
ms = ''
login = data['MyDate'][0]['login']
password = data['MyDate'][0]['password']
mail = data['MyDate'][0]['login'].split('#')[1]
if ('yandex' in mail) or ('ya' in mail):
ms = 'yandex.ru'
elif 'gmail' in mail:
ms = 'gmail.com'
elif 'mail' in mail:
ms = 'mail.ru'
url = data['Mail'][0][ms]
number, topic, message = message_topic.split('$')
toaddr = data['MyFriend'][0]['mail'][int(number)]
msg = MIMEMultipart()
msg['Subject'] = topic
msg['From'] = login
body = message
msg.attach(MIMEText(body, 'plain'))
try:
server = root.SMTP_SSL(url, 465)
except:
print('no connect')
server.login(login, password)
server.sendmail(login, toaddr, msg.as_string())
server.quit()
bot.send_message(id_user, 'Ваше сообщение отправлено')
I tried to overwrite variables and tried to use other mail, but to no avail

ValueError: There may be at most 1 To headers in a message

I am trying to write a very basic email sending script. Here is my code ..
import smtplib
from email.message import EmailMessage
msg = EmailMessage()
msg.set_content("Test message.")
msg['Subject'] = "Test Subject!!!"
msg['From'] = "myemail#gmail.com"
email_list = ["xyz#gmail.com", "abc#gmail.com"]
for email in email_list:
msg['To'] = email
server = smtplib.SMTP(host='smtp.gmail.com', port=587)
server.starttls()
server.login("myemail#gmail.com", "mypassword")
server.send_message(msg)
server.quit()
the script should send mail to multiple recipients so, I need to change the msg['To'] field when iterating through loop But I get the following error in traceback bellow.
Traceback (most recent call last):
File "exp.py", line 66, in <module>
msg['To'] = email
File "/usr/lib/python3.8/email/message.py", line 407, in __setitem__
raise ValueError("There may be at most {} {} headers "
ValueError: There may be at most 1 To headers in a message
How do I solve ? Please help. Thank you..
Clean the 'To' property of the message.
for email in email_list:
msg['To'] = email
server = smtplib.SMTP(host='smtp.gmail.com', port=587)
server.starttls()
server.login("myemail#gmail.com", "mypassword")
server.send_message(msg)
server.quit()
del msg['To]
Below is the code that throws the exception: (\Python385\Lib\email\message.py)
def __setitem__(self, name, val):
"""Set the value of a header.
Note: this does not overwrite an existing header with the same field
name. Use __delitem__() first to delete any existing headers.
"""
max_count = self.policy.header_max_count(name)
if max_count:
lname = name.lower()
found = 0
for k, v in self._headers:
if k.lower() == lname:
found += 1
if found >= max_count:
raise ValueError("There may be at most {} {} headers "
"in a message".format(max_count, name))
self._headers.append(self.policy.header_store_parse(name, val))
Not knowing the inner working of the EmailMessage class, what I can assume is that every call to __setitem__ writes to the head of the email message, so by calling it in a loop, the header is being written multiple times, what I'd recommend is that you make an email message for every email you'll send, but create only one server:
server = smtplib.SMTP(host='smtp.gmail.com', port=587)
server.starttls()
server.login("myemail#gmail.com", "mypassword")
email_list = ["xyz#gmail.com", "abc#gmail.com"]
for email in email_list:
msg = EmailMessage()
msg.set_content("Test message.")
msg['Subject'] = "Test Subject!!!"
msg['From'] = "myemail#gmail.com"
msg['To'] = email
server.send_message(msg)
server.quit()
Only if you need for the messages to be sent separately. If you want to send the same message to everyone at the same time you could do something like
msg['To'] = ', '.join(email_list)
If you have a list of addresses, and some of them include a name/title, then I think this is the correct way to do it. Please note that parseaddr + formataddr pair may not be needed, but parseaddr can correct some malformed recipients.
from email.header import Charset
from email.message import EmailMessage, MIMEPart
from email.utils import formataddr, parseaddr
test_recipients = [
"Mr. John Doe <johndoe#example.com>",
"Mr. Jane Doe <janedoe#example.com>",
"somebody#example.com"
]
to_header= []
for raw_address in (test_recipients):
# Parse and recreate
title, email = parseaddr(raw_address)
if title and email:
to_header.append(f"{title} <{email}>")
elif email:
to_header.append(email)
# Encode after join
message.add_header("To", Charset("utf-8").header_encode(", ".join(to_header)))
if you just delete
server.quit() from loop
and add
del msg['to']
then there is no error

python email sent and received with smtplib has no content

I am sending email with my raspberrypi with python.
I successfully sent and received the message, but the content is missing.
Here is my code
import smtplib
smtpUser = 'myemail#gmail.com'
smtpPass = 'mypassword'
toAdd = 'target#gmail.com'
fromAdd = smtpUser
subject = 'Python Test'
header = 'To: ' + toAdd + '\n' + 'From: ' + fromAdd + '\n' + 'Subject: ' + subject
body = 'From within a Python script'
msg = header + '\n' + body
print header + '\n' + body
s = smtplib.SMTP('smtp.gmail.com',587)
s.ehlo()
s.starttls()
s.ehlo()
s.login(smtpUser,smtpPass)
s.sendmail(fromAdd, toAdd, msg)
s.quit()
Thank you for your attention!
I wrote a wrapper around sending emails in python; it makes sending emails super easy: https://github.com/krystofl/krystof-utils/blob/master/python/krystof_email_wrapper.py
Use it like so:
emailer = Krystof_email_wrapper()
email_body = 'Hello, <br /><br />' \
'This is the body of the email.'
emailer.create_email('sender#example.com', 'Sender Name',
['recipient#example.com'],
email_body,
'Email subject!',
attachments = ['filename.txt'])
cred = { 'email': 'sender#example.com', 'password': 'VERYSECURE' }
emailer.send_email(login_dict = cred, force_send = True)
You can also look at the source code to find how it works.
The relevant bits:
import email
import smtplib # sending of the emails
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
self.msg = MIMEMultipart()
self.msg.preamble = "This is a multi-part message in MIME format."
# set the sender
author = email.utils.formataddr((from_name, from_email))
self.msg['From'] = author
# set recipients (from list of email address strings)
self.msg['To' ] = ', '.join(to_emails)
self.msg['Cc' ] = ', '.join(cc_emails)
self.msg['Bcc'] = ', '.join(bcc_emails)
# set the subject
self.msg['Subject'] = subject
# set the body
msg_text = MIMEText(body.encode('utf-8'), 'html', _charset='utf-8')
self.msg.attach(msg_text)
# send the email
session = smtplib.SMTP('smtp.gmail.com', 587)
session.ehlo()
session.starttls()
session.login(login_dict['email'], login_dict['password'])
session.send_message(self.msg)
session.quit()

python smtplib multipart email body not showing on iphone

I am trying to send an email with an image using smtplib in python. The email shows up fine on my desktop and on the iphone gmail app, but on the standard iphone mail app the body doesn't appear. Here is my code:
def send_html_email(self, subject, html, to_email,from_email, password, from_name, image=None):
msg = MIMEMultipart('alternative')
msg['From'] = from_name
msg['To'] = to_email
msg['Subject'] = subject
html_message = MIMEText(html, "html")
msg.attach(html_message)
if image:
msgImage = MIMEImage(image)
msgImage.add_header('Content-ID', '<image1>')
msg.attach(msgImage)
session = smtplib.SMTP("smtp.gmail.com:587")
session.starttls()
session.login(from_email, password)
session.sendmail(from_email, to_email, msg.as_string().encode('utf-8'))
session.quit()
It seems that when I do not add an image, the email sends fine with the body. Any ideas on how to get it working with the image as well?
This appears to work:
def send_html_email(self, subject, html, to_email, from_email, password, from_name, image=None):
msgRoot = MIMEMultipart('related')
msgRoot['From'] = from_name
msgRoot['To'] = to_email
msgRoot['Subject'] = subject
msg = MIMEMultipart('alternative')
msgRoot.attach(msg)
html_message = MIMEText(html, "html")
msg.attach(html_message)
if image:
msgImage = MIMEImage(image)
msgImage.add_header('Content-ID', '<image1>')
msgRoot.attach(msgImage)
session = smtplib.SMTP("smtp.gmail.com:587")
session.starttls()
session.login(from_email, password)
session.sendmail(from_email, to_email, msgRoot.as_string().encode('utf-8'))
session.quit()

Email multiple recipients Python

I'm trying to email multiple recipients using the pyton script below. I've searched the forum for answers, but have not been able to implement any of them correctly. If anyone has a moment to review my script and spot/resolve the problem it would be greatly appreciated.
Here's my script, I gather my issue is in the 'sendmail' portion, but can't figure out how to fix it:
gmail_user = "sender#email.com"
gmail_pwd = "sender_password"
recipients = ['recipient1#email.com','recipient2#email.com']
def mail(to, subject, text, attach):
msg = MIMEMultipart()
msg['From'] = gmail_user
msg['To'] = ", ".join(recipients)
msg['Subject'] = subject
msg.attach(MIMEText(text))
part = MIMEBase('application', 'octet-stream')
part.set_payload(open(attach, 'rb').read())
Encoders.encode_base64(part)
part.add_header('Content-Disposition',
'attachment; filename="%s"' % os.path.basename(attach))
msg.attach(part)
mailServer = smtplib.SMTP("smtp.gmail.com", 587)
mailServer.ehlo()
mailServer.starttls()
mailServer.ehlo()
mailServer.login(gmail_user, gmail_pwd)
mailServer.sendmail(gmail_user, to, msg.as_string())
mailServer.close()
mail("recipient1#email.com, recipient2#email.com",
"Subject",
"Message",
"attchachment")
Any insight would be greatly appreciated.
Best,
Matt
It should be more like
mail(["recipient1#email.com", "recipient2#email.com"],
"Subject",
"Message",
"attchachment")
You already have a array of recipients declared,that too globally,You can use that without passing it as an argument to mail.
I wrote this bit of code to do exactly what you want. If you find a bug let me know (I've tested it and it works):
import email as em
import smtplib as smtp
import os
ENDPOINTS = {KEY: 'value#domain.com'}
class BoxWriter(object):
def __init__(self):
pass
def dispatch(self, files, box_target, additional_targets=None, email_subject=None, body='New figures'):
"""
Send an email to multiple recipients
:param files: list of files to send--requires full path
:param box_target: Relevant entry ENDPOINTS dict
:param additional_targets: other addresses to send the same email
:param email_subject: optional title for email
"""
destination = ENDPOINTS.get(box_target, None)
if destination is None:
raise Exception('Target folder on Box does not exist')
recipients = [destination]
if additional_targets is not None:
recipients.extend(additional_targets)
subject = 'Updating files'
if email_subject is not None:
subject = email_subject
message = em.MIMEMultipart.MIMEMultipart()
message['From'] = 'user#domain.com'
message['To'] = ', '.join(recipients)
message['Date'] = em.Utils.formatdate(localtime=True)
message['Subject'] = subject
message.attach(em.MIMEText.MIMEText(body + '\n' +'Contents: \n{0}'.format('\n'.join(files))))
for f in files:
base = em.MIMEBase.MIMEBase('application', "octet-stream")
base.set_payload(open(f, 'rb').read())
em.Encoders.encode_base64(base)
base.add_header('Content-Disposition', 'attachment; filename={0}'.format(os.path.basename(f)))
message.attach(base)
conn = smtp.SMTP('smtp.gmail.com', 587)
un = 'user#gmail.com'
pw = 'test1234'
conn.starttls()
conn.login(un, pw)
conn.sendmail('user#domain.com', recipients, message.as_string())
conn.close()
I was facing the same issue, I fixed this issue now. Here is my code -
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
import smtplib
import datetime
def sendMail():
message = MIMEMultipart()
message["To"] = "xxxxx#xxxx.com,yyyy#yyyy.com"
message["Cc"] = "zzzzzz#gmail.com,*********#gmail.com"
message["From"] = "xxxxxxxx#gmail.com"
message["Password"] = "***************"
server = 'smtp.gmail.com:587'
try:
now = datetime.datetime.now()
message['Subject'] = "cxxdRL Table status (Super Important Message) - "+str(now)
server = smtplib.SMTP(server)
server.ehlo()
server.starttls()
server.login(message["From"], message["Password"])
server.sendmail(message["From"], message["To"].split(",") + message["Cc"].split(","), message.as_string())
server.quit()
print('Mail sent')
except:
print('Something went wrong...')
sendMail()

Categories

Resources