I've written a Python script to automatically send some information to my friends. I used SMTPlib, it works well if I only sent to me or one additional email.
When I try to send to 17 emails, (including my sender email), then it shows in sent mail on web-based Gmail. I saw that the mail was sent but I didn't receive it. Only the first recipient received the email.
If I reply to all from that mail, then everyone got only that reply.
I can't figure out why they didn't receive it when I sent it from script, I ask my friend check spam, but she didn't find anything.
This is my code:
#!/usr/bin/env python
import smtplib
import csv
from datetime import datetime, timedelta
SMTP_SERVER = 'smtp.gmail.com'
SMTP_PORT = 587
sender = 'MYBOT#gmail.com'
password = None
with open('pass', 'rt') as f:
password = f.read().strip('\n')
def send_mail(recipient, subject, body):
"""
Send happy bithday mail
"""
headers = ["From: " + sender,
"Subject: " + subject,
"To: " + recipient,
"MIME-Version: 1.0",
"Content-Type: text/html"]
headers = "\r\n".join(headers)
smtp = smtplib.SMTP(SMTP_SERVER, SMTP_PORT)
smtp.ehlo()
smtp.starttls()
smtp.ehlo
smtp.login(sender, password)
body = "" + body +""
smtp.sendmail(sender, recipient, headers + "\r\n\r\n" + body)
print "Sent to ",
print recipient
smtp.quit()
def send_happybirthday(recipient):
body = """Happy birthday to you!
\n<br/>From C2k8pro with love
"""
subject ='[BirthReminder] Happy birthday to you! from C2k8pro'
send_mail(recipient, subject, body)
def send_notification(all_mails, names):
body = """Tomorrow is birthday of %s""" % names
send_mail(all_mails, body, body)
def test_send_mail():
notify_body = """Tomorrow is birthday of """
recipients = ['MYBOT#gmail.com']
today = datetime.now()
format = "%d-%m-%Y"
print today
today_in_str = datetime.strftime(today, format)
def read_csv():
FILENAME = 'mails.csv'
reader = csv.reader(open(FILENAME, 'rt'), delimiter=',')
today = datetime.now()
one_day = timedelta(days=1)
tomorrow = today + one_day
all_mails = []
str_format = "%d/%m"
str_today = today.strftime(str_format)
str_tomorrow = tomorrow.strftime(str_format)
print 'Today is ', str_today
tomorrow_birth = []
for row in reader:
name = row[1].strip()
dob = row[2]
dmy = dob.split("/")
mail = row[3]
all_mails.append(mail)
#TODO fix dob with only 1 digit
birth_date = dmy[0] + "/" + dmy[1]
if str_today == birth_date:
print 'Happy birthday %s' % name
try:
send_happybirthday(mail)
except Exception, e:
print e
elif str_tomorrow == birth_date:
tomorrow_birth.append(name)
print "Tomorrow is %s's birthday" % name
# Remove empty string
all_mails = filter(None, all_mails)
print 'All mails: ', len(all_mails)
str_all_mails = ', '.join(all_mails)
if tomorrow_birth:
all_tomorrow = ', '.join(tomorrow_birth)
send_notification(str_all_mails, all_tomorrow)
def main():
read_csv()
if __name__ == "__main__":
main()
Can anyone explain this. Thanks!
I found solution from here
Send Email to multiple recipients from .txt file with Python smtplib
I passed a string contain all recipients separated by comma to msg['To'] and sendmail().
It's true for msg['To'] but with sendmail, I have to use a list.
Related
I took an example of automation from a book (Automate tasks with Python) which consists of opening and reading a spreadsheet and checking if the fee has been paid, if not, send an email to the client informing him. But when I run the code it doesn't show any error, but also, nothing happens. I would appreciate it if you could help me, and still recommend a library to carry out the process, if necessary.
Follow the code below:
import openpyxl, smtplib, sys
wb = openpyxl.load_workbook('C:/temp/cobranca.xlsx')
sheet = wb['Sheet1']
lastCol = sheet.max_column
latestMonth = sheet.cell(row=1, column=lastCol).value
unpaidMembers = {}
for r in range(2, sheet.max_row + 1):
payment = sheet.cell(row=r, column=lastCol).value
if payment != 'ok':
name = sheet.cell(row=r, column=1).value
email = sheet.cell(row=r, column=2).value
unpaidMembers[name] = email
smtpObj = smtplib.SMTP('mail.omnia.net.br', 465)
smtpObj.ehlo()
smtpObj.starttls()
smtpObj.login('dp.contabil#omnia.net.br', sys.argv[1])
for name, email in unpaidMembers.items():
body = "Subject: %s dues unpaid. \n Dear %s, \n Records show that you have not paid dues for %s. Please make this payment as soon as possible. Thank you!'" % (latestMonth, name, latestMonth)
print('Sending email to %s...' % email)
sendmailStatus = smtpObj.sendmail('dp.contabil#omnia.net.br', email, body)
if sendmailStatus != {}:
print('There was a problem sendind email to %s: %s' % (email, sendmailStatus))
smtpObj.quit()
Here is an example which I used:
import smtplib
from string import Template
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
MY_ADDRESS = 'XYZ#gmail.com'
PASSWORD = 'YourPassword'
def get_contacts(filename):
names = []
emails = []
with open(filename, mode='r', encoding='utf-8') as contacts_file:
for a_contact in contacts_file:
names.append(a_contact.split()[0])
emails.append(a_contact.split()[1])
return names, emails
def read_template(filename):
with open(filename, 'r', encoding='utf-8') as template_file:
template_file_content = template_file.read()
return Template(template_file_content)
def main():
names, emails = get_contacts('C:/Users/xyz/Desktop/mycontacts.txt') # read contacts
message_template = read_template('C:/Users/xyz/Desktop/message.txt')
s = smtplib.SMTP(host='smtp.gmail.com', port=587)
s.starttls()
s.login(MY_ADDRESS, PASSWORD)
for name, email in zip(names, emails):
msg = MIMEMultipart() # create a message
message = message_template.substitute(PERSON_NAME=name.title())
print(message)
msg['From'] = MY_ADDRESS
msg['To'] = email
msg['Subject'] = "Sending mail to all"
msg.attach(MIMEText(message, 'plain'))
s.send_message(msg)
del msg
s.quit()
if __name__ == '__main__':
main()
I'm finding it very difficult to modify this code to send to send to multiple recipients, I have tried many variations of the examples already out there. I'm very new to python so any help would be much appreciated.
It is as part of safety system I am designing to alert parents and carers of potential elopement risk for children and adults with ASD.
'''
import time
import serial
import smtplib
TO = 'email#mail.org'
GMAIL_USER = 'email#gmail.com'
GMAIL_PASS = 'passowrd'
SUBJECT = 'Security Alert'
TEXT = 'Movement detected!'
ser = serial.Serial('COM6', 9600)
def send_email():
print("Sending Email")
smtpserver = smtplib.SMTP("smtp.gmail.com",587)
smtpserver.ehlo()
smtpserver.starttls()
smtpserver.ehlo
smtpserver.login(GMAIL_USER, GMAIL_PASS)
header = 'To:' + TO + '\n' + 'From: ' + GMAIL_USER
header = header + '\n' + 'Subject:' + SUBJECT + '\n'
print header
msg = header + '\n' + TEXT + ' \n\n'
smtpserver.sendmail(GMAIL_USER, TO, msg)
smtpserver.close()
while True:
message = ser.readline()
print(message)
if message[0] == 'M' :
send_email()
time.sleep(0.5)
'''
Send the alert to multiple people.
Have you had a look at this yet? How to send email to multiple recipients using python smtplib?
It looks like you might be dropping some of the pieces of your header too by overwriting them:
header = 'From: ' + GMAIL_USER
Instead of:
header = header + 'From: ' + GMAIL_USER
You might also want to consider using format instead, but I'm already out of my depth on Python :-)
I have been working on a small email utility in Python after following an online tutorial. The only issue seems to be the data I am printing is None. For example, the sender and subject of the email, when printed, are None. Here is my code:
import imaplib
import email
class email_account:
#u: email username
#domain: email domain
#pwd: email account password
#smtp_server: SMTP server for email account. I.e. "imap.gmail.com"
#smtp_port: SMTP server port number. I.e. 993
def __init__(self, u, domain, pwd, smtp_server, smtp_port):
self.u = u
self.domain = domain
self.pwd = pwd
self.smtp_server = smtp_server
self.smtp_port = smtp_port
#extracts information from an email
def read_email(self, mail):
return None
#open the inbox for the email account and get the IDs of all emails
def open_inbox(self, mail):
mail.select("inbox")
type, data = mail.search(None, "all")
mail_ids = data[0]
id_list = mail_ids.split()
#get ID of first and last email
first_id = int(id_list[0])
last_id = int(id_list[-1])
print("First ID: " + str(first_id) + " -> " + str(int(last_id)))
#iterate through all emails retrieved from the inbox
for x in range(first_id, last_id, 1):
print("RAN")
t, d = mail.fetch(str(x), "(RFC822)")
for message_parts in d:
print(isinstance(message_parts[1], str))
message = email.message_from_string(str(message_parts[1]))
subject = message["subject"]
sender = message["from"]
print("From: " + str(sender) + "\n")
print("Subject: " + str(subject) + "\n")
#login to the email account with the provided credentials
def login(self):
mail = imaplib.IMAP4_SSL(self.smtp_server)
mail.login(self.u, self.pwd)
self.open_inbox(mail)
new_email = email_account("my_email", "#gmail.com", "password", "imap.gmail.com", 993)
new_email.login()
'print("From: " + str(sender) + "\n")' prints out From: None and print("Subject: " + str(subject) + "\n") prints out Subject: None. What is going on here?
I have four python functions that I am using to send mail. If the program does one thing, it mails a set of results to a multiple recipients, if it does another thing, a separate function mails the results to one recipient.
def smail(to,sub,body):
addr_from = 'alert#example.com'
msg = MIMEMultipart()
msg['From'] = addr_from
msg['To'] = to
msg['Subject'] = sub
msg.attach(body)
s = smtplib.SMTP('webmail.example.com')
s.sendmail(addr_from, [to], msg.as_string())
s.quit()
def email_format2(results):
text = ""
text += 'The following applications in <environment> are non-compliant\n'
text += '<br>'
text += 'Here are there names and locations. Please inform the developer.'
text += '<br>'
text += '<br>'
table = pd.DataFrame.from_records(results)
table_str = table.to_html()
text += "%s" % table_str
return text
def mail_results_aq(results):
body = email_format2(results)
msg = MIMEText(body, 'html')
sub = "Placeholder subject"
to = 'email1#example.com, email2#example.com, email3#example.com'
smail(to, sub, msg)
def mail_results_prd(results):
body = email_format2(results)
msg = MIMEText(body, 'html')
sub = "Placeholder subject"
to = 'email4#example.com'
smail(to, sub, msg)
The mail_results_aq function will only email results to the first recipient (email1#example.com).
In other questions similar to this one, I've seen a the recipients being entered into a list i.e
import smtplib
from email.mime.text import MIMEText
s = smtplib.SMTP('smtp.uk.xensource.com')
s.set_debuglevel(1)
msg = MIMEText("""body""")
sender = 'me#example.com'
recipients = ['john.doe#example.com', 'john.smith#example.co.uk']
msg['Subject'] = "subject line"
msg['From'] = sender
msg['To'] = ", ".join(recipients)
s.sendmail(sender, recipients, msg.as_string())
However, this use case only seems to work when used in the same function. How can I implement this feature across the four functions I have above?
Thanks in advance!
I created a script who send mail whith a specific output took from a server.
I splited this output and each element I sent it to a html cell.
I also created a header for the table what is looks like that:
def get_html_table_header(*column_names):
header_string = '<tr width=79 style="background:#3366FF;height:23.25pt;font-size:8.0pt;font-family:Arial,sans-serif;color:white;font-weight:bold;" >'
for column in column_names:
if column is not None:
header_string += '<td>' + column + '</td>'
header_string += '</tr>'
return header_string
def get_concrete_html_table_header():
return get_html_table_header('Num. Row','Cell1','Cell2','Cell3','Comment (enter your feedback below)','Cell4','Cell5','Cell6','Cell7','Cell8','Cell9','Cell10')
When I print the result of this function in linux konsole, it looks like that:
<tr width=79 style="background:#3366FF;height:23.25pt;font-size:8.0pt;font-family:Arial,sans-serif;color:white;font-weight:bold;" ><td>Num. Row</td><td>Cell1</td><td>Cell2</td><td>Cell3</td><td>Comment (enter your feedback below)</td><td>Cell4</td><td>Cell5</td><td>Cell6</td><td>Cell7</td><td>Cell8</td><td>Cell9</td><td>Cell10</td></tr>
When I receive the email, source looks like that:
<tr width="79" style="background:#3366FF;height:23.25pt;font-size:8.0pt;font-family:Arial,sans-serif;color:white;font-weight:bold;"><td>Num. Row</td><td>Cell1</td><td>Cell2</td><td>Cell3</td><td>Comment (enter your feedback below)</td><td>Cell4</td><td>Cell5</td><td>Cell6</td><td>Cell7</td><td>Cell8</td><td>Cell9</td>< td>Cell10</td></tr>
To build email body I`m using function:
def build_email_body(CRs_list):
global criterial_number
if 0 == len(CRs_list):
return None
email_body = ''
email_body += '<html><head><title>My Title</title></head><body>'
email_body += '<p align="center"><font color="#176b54" size="+2"><b>Some info</b></font></p>'
email_body += '<p align="center"><font color="#176b54" size="+1">Another info</font></p>'
email_body += '<table align="center" BORDER=1 CELLSPACING=2 CELLPADDING=2 COLS=3 WIDTH="100%">'
email_body += get_concrete_html_table_header()
for CR in CRs_list:
email_body += get_html_table_row()#create row for every output received(11 cells for every output, according with the header)
email_body += '</table>'
email_body += '</table><br><p align="left"><font color="#176b54" size="+1"><b>=> This is an automatic generated email via script<br>'
email_body += '<br><br>Have a nice day!</b></font></p><br></body></html>'
return email_body
To send email I`m using function:
def send_email(body, recipients, subject, file):
#inform just sender
if None == body:
body = "WARNING -> NO entries retrieved after 5 retries<br>CRAU output:<br>" + dct_newCRs_output + "<br>" + duration
#override recipients to not set junk info
recipients = sender
email = Email(SMTP_SERVER, SENDER, recipients, _CC, subject, body, 'html', file)
email.send()
send() is imported from class Email:
import os, smtplib
from email import encoders
from email.mime.audio import MIMEAudio
from email.mime.base import MIMEBase
from email.mime.image import MIMEImage
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
import mimetypes
class Email:
__config = {}
def __init__(self, smtp_server, sender, recipients, cc, subject, body, body_type, attachments=None):
self.__config = {'smtp_server': smtp_server,
'sender': sender,
'recipients': recipients,
'cc': cc,
'subject': subject,
'body':body,
'body_type':body_type, #plain|html
'attachments':attachments #list of files
}
def getSmtpServer(self):
return self.__config.get('smtp_server')
def getSender(self):
return self.__config.get('sender')
def getRecipients(self):
return self.__config.get('recipients')
def getCc(self):
return self.__config.get('cc')
def getSubject(self):
return self.__config.get('subject')
def getBody(self):
return self.__config.get('body')
def getBodyType(self):
return self.__config.get('body_type')
def getAttachments(self):
return self.__config.get('attachments')
def setSmtpServer(self, host):
self.__config['smtp_server'] = smtp_server
return self
def setSender(self, sender):
self.__config['sender'] = sender
return self
def setRecipients(self, recipients):
self.__config['recipients'] = recipients
return self
def setCc(self, cc):
self.__config['cc'] = cc
return self
def setSubject(self, subject):
self.__config['subject'] = subject
return self
def setBody(self, body):
self.__config['body'] = body
return selfMIMEMultipart
def setBodyType(self, body_type):
self.__config['body_type'] = body_type
return self
def setAttachments(self, attachments):
self.__config['attachments'] = attachments
return self
def attachFilesToEmail(self, attachments, msg):
if None == attachments:
tmpmsg = msg
msg = MIMEMultipart()
msg.attach(tmpmsg)
if None != attachments:
for fname in attachments:
if not os.path.exists(fname):
print "File '%s' does not exist. Not attaching to email." % fname
continue
if not os.path.isfile(fname):
print "Attachment '%s' is not a file. Not attaching to email." % fname
continue
# Guess at encoding type
ctype, encoding = mimetypes.guess_type(fname)
if ctype is None or encoding is not None:
# No guess could be made so use a binary type.
ctype = 'application/octet-stream'
maintype, subtype = ctype.split('/', 1)
if maintype == 'text':
fp = open(fname)
attach = MIMEText(fp.read(), _subtype=subtype)
fp.close()
elif maintype == 'image':
fp = open(fname, 'rb')
attach = MIMEImage(fp.read(), _subtype=subtype)
fp.close()
elif maintype == 'audio':
fp = open(fname, 'rb')
attach = MIMEAudio(fp.read(), _subtype=subtype)
fp.close()
else:
fp = open(fname, 'rb')
attach = MIMEBase(maintype, subtype)
attach.set_payload(fp.read())
fp.close()
# Encode the payload using Base64
encoders.encode_base64(attach)
# Set the filename parameter
filename = os.path.basename(fname)
attach.add_header('Content-Disposition', 'attachment', filename=filename)
msg.attach(attach)
def send(self):
# Create message container - the correct MIME type is multipart/alternative.
msg = MIMEMultipart('alternative')
msg['Subject'] = self.getSubject()
msg['From'] = self.getSender()
msg['To'] = self.getRecipients()
msg['CC'] = self.getCc()
# Record the MIME types of both parts - text/plain and text/html.
#part1 = MIMEText(text, 'plain')
#part2 = MIMEText(html, 'html')
part = MIMEText(self.getBody(), self.getBodyType())
# Attach parts into message container.
# According to RFC 2046, the last part of a multipart message, in this case
# the HTML message, is best and preferred.
msg.attach(part)
# Add attachments, if any
self.attachFilesToEmail(self.getAttachments(), msg)
# Send the message via local SMTP server.
s = smtplib.SMTP(self.getSmtpServer())
# sendmail function takes 3 arguments: sender's address, recipient's address
# and message to send - here it is sent as one string.
s.sendmail(self.getSender(), (self.getRecipients() + self.getCc()).split(","), msg.as_string())
s.quit()
I hope is enough information.
Can someone explain to me, why is happening this and how can I fix it?
Your code looks correct, the problem is elsewhere.
< is what you get when you add < as text to a HTML document (since < means "start new element", you need to escape this character in plain text).
The interesting part here is why does it happen only once in the whole string. If all the < had been replaced, my guess would be that you accidentally added the table as text to the HTML body of the mail.
Maybe the space in < td> is a clue: Mails shouldn't have more than 72 characters per line. So maybe some mail server wraps the HTML? Outlook is known to mess a lot with the mails it receives.
Try to send the HTML code as multipart attachment. See Sending HTML email using Python