Automating email delivery - python

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()

Related

Python/smtplib - automation for sending email

I am developing an application to automate the sending of emails from the collection department where I work. It consists of accessing an excel spreadsheet, reading the column that is missing the payment and sending an automatic email to the customer. The code works, but it sends the email only to the last person who did not make the payment and not to everyone. can you help me? Follow the code below:
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
import smtplib
from datetime import date
import openpyxl
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
print(unpaidMembers)
# create message object instance
msg = MIMEMultipart()
# setup the parameters of the message
password = "example"
msg['From'] = "example#example.com"
msg['To'] = email
msg['Subject'] = "%s - Honorário em aberto." % (name)
for name, email in unpaidMembers.items():
body = "Prezado(a) %s. \n \n Em nosso sistema consta, em sua conta, o honorário referente ao mês %s/2020 em aberto, pedimos sua regularização imediata. \n \n Caso o pagamento já tenha sido efetuado, por favor, desconsidere este e-mail. \n \n \n Att, \n OMNIA Tecnologia" % (
name, latestMonth)
print('Sending email to %s...' % email)
# add in the message body
msg.attach(MIMEText(body))
# create server
server = smtplib.SMTP('stmp.example.net', 587)
server.starttls()
# Login Credentials for sending the mail
server.login(msg['From'], password)
# send the message via the server.
server.sendmail(msg['From'], msg['To'], msg.as_string())
server.quit()
print("successfully sent email to %s:" % (msg['To']))
msg['To'] can be given a list of email addresses. Possibly making a list as shown below is an option.
email=[]
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.append(sheet.cell(row=r, column=2).value)
unpaidMembers[name] = email
print(unpaidMembers)
then
msg['To'] = email

Why email is not being send to CC list?

I have the following code where the Cc email list is not working meaning emails are not received to the folks/groups in Cc list,email to To list is working,I just can't figure out what is wrong?any guidance on how to debug and fix it?
import time,smtplib
import pprint,logging,os,time,json
from subprocess import Popen, PIPE, call
from pprint import pprint
from email.mime.text import MIMEText
from email.MIMEMultipart import MIMEMultipart
from email.MIMEBase import MIMEBase
email = 'username2#company.com'
gerriturl = ""
def sendEmail2(type,data):
global originalchange
global gerriturl,email,username1
body = '''%s''' % (data)
#msg = MIMEMultipart(body)
msg = MIMEMultipart()
sender = 'techci#company.com'
receivers = []
cc = ['username1#company.com']
REPLY_TO_ADDRESS = 'embedded-tech-integrators#group.company.com'
if type =='failure':
print("Inside failure email %s"%email)
b = '\U0001F6A8'
print("b.decode('unicode-escape')")
receivers.append('username2#company.com')
#receivers.append(email)
print('%s'%receivers)
msg['Subject'] = '%s AUTO FAILED FOR GERRIT %s :PLEASE TAKE IMMEDIATE ACTION!!!'%(b.decode('unicode-escape'),gerriturl)
msg['From'] = sender
msg['To'] = ', '.join(receivers)
msg['Cc'] = ', '.join(cc)
msg["Content-Type"] = "text/html"
try:
mail = smtplib.SMTP('relay.company.com', 25)
msg.attach(MIMEText(body, 'html'))
msg.add_header('reply-to', REPLY_TO_ADDRESS)
print('Email sent successfully %s %s'%(receivers,cc))
except Exception as e:
logger.error('Problem sending email')
logger.error('%s' % e)
def main():
data = "THIS IS A TEST EMAIL"
sendEmail2('failure',data)
if __name__ == "__main__":
main()
The important thing is to pass the complete list of recipient email addresses to the sendmail() method - you need to concatenate the email addresses for the To, CC and BCC fields into a single list, not a string.
import smtplib
def send_email(subject, body_text, emails_to, emails_cc=[], emails_bcc=[]):
# Configuration
host = "localhost"
port = 1025
from_addr = "nobody#somewhere.com"
# Build the email body
body = "\r\n".join([
"From: %s" % from_addr,
"To: %s" % ', '.join(emails_to),
"CC: %s" % ', '.join(emails_cc),
"Subject: %s" % subject ,
"",
body_text
])
# Prepare the complete list of recipient emails for the message envelope
emails = emails_to + emails_cc + emails_bcc
# Connect to the server
server = smtplib.SMTP(host, port)
# Send the email
server.sendmail(from_addr, emails, body)
# Close the server connection
server.quit()

Mail is going out 3 times instead of once to each address?

I have come up with something which seems weird to me and I am not sure what exactly to search for.
import smtplib, openpyxl, sys
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.base import MIMEBase
from email import encoders
wb = openpyxl.load_workbook('Book1.xlsx')
sheet = wb.get_sheet_by_name('Sheet1')
lastCol = sheet.max_column
latestMonth = sheet.cell(row=1, column=lastCol).value
recipients = []
unpaidMembers = {}
for r in range(2, sheet.max_row + 1):
payment = sheet.cell(row=r, column=lastCol).value
if payment != 'Y':
name = sheet.cell(row=r, column=1).value
email = sheet.cell(row=r, column=2).value
unpaidMembers[name] = email
recipients.append(email)
fromaddr = "xxxx#xxxx.com"
for n in recipients:
msg = MIMEMultipart()
msg['From'] = fromaddr
msg['To'] = n
msg['Subject'] = "Hi"
body = "This is a test mail"
msg.attach(MIMEText(body, 'plain'))
filename = "xxx.pdf"
attachment = open("\\Users\xxx\xxx\xxx.pdf","rb")
part = MIMEBase('application', 'octet-stream')
part.set_payload((attachment).read())
encoders.encode_base64(part)
part.add_header('Content-Disposition', "attachment; filename= %s" % filename)
msg.attach(part)
smtp0bj = smtplib.SMTP('smtp-mail.outlook.com', 587)
smtp0bj.ehlo()
smtp0bj.starttls()
smtp0bj.login(fromaddr, 'xxxxx')
text = msg.as_string()
smtp0bj.sendmail(fromaddr, recipients, text)
smtp0bj.quit()
I am guessing that the for-loop is being executed 3 times(there are 3 items in the list. I am at a loss about how to make it execute only once.
You basically do that :
for n in recipients: # for each recipient
smtp0bj.sendmail(fromaddr, recipients, text) # send mail to all recipients
So at each pass it sends the mail to all the recipients.
So if you have 3 recipients, they'll receive 3 mails each.
Replace with :
smtp0bj.sendmail(fromaddr, n, text)
Also I'm not sure, and can't test right now, but I believe 'to' has to be a list.
So if the above solution doesn't work, give this a shot :
smtp0bj.sendmail(fromaddr, [n], text)

Python SMTP/MIME Message body

I've been working on this for 2 days now and managed to get this script with a pcapng file attached to send but I cannot seem to make the message body appear in the email.
import smtplib
import base64
import ConfigParser
#from email.MIMEapplication import MIMEApplication
#from email.MIMEmultipart import MIMEMultipart
#from email.MIMEtext import MIMEText
#from email.utils import COMMASPACE, formatdate
Config = ConfigParser.ConfigParser()
Config.read('mailsend.ini')
filename = "test.pcapng"
fo = open(filename, "rb")
filecontent = fo.read()
encoded_content = base64.b64encode(filecontent) # base 64
sender = 'notareal#email.com' # raw_input("Sender: ")
receiver = 'someother#fakeemail.com' # raw_input("Recipient: ")
marker = raw_input("Please input a unique set of numbers that will not be found elsewhere in the message, ie- roll face: ")
body ="""
This is a test email to send an attachment.
"""
# Define the main headers
header = """ From: From Person <notareal#email.com>
To: To Person <someother#fakeemail.com>
Subject: Sending Attachment
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary=%s
--%s
""" % (marker, marker)
# Define message action
message_action = """Content-Type: text/plain
Content-Transfer-Encoding:8bit
%s
--%s
""" % (body, marker)
# Define the attachment section
message_attachment = """Content-Type: multipart/mixed; name=\"%s\"
Content-Transfer-Encoding:base64
Content-Disposition: attachment; filename=%s
%s
--%s--
""" % (filename, filename, encoded_content, marker)
message = header + message_action + message_attachment
try:
smtpObj = smtplib.SMTP('smtp.gmail.com')
smtpObj.sendmail(sender, receiver, message)
print "Successfully sent email!"
except Exception:
print "Error: unable to send email"
My goal is to ultimately have this script send an email after reading the parameters from a config file and attach a pcapng file along with some other text data describing the wireshark event. The email is not showing the body of the message when sent. The pcapng file is just a test file full of fake ips and subnets for now. Where have I gone wrong with the message body?
def mail_man():
if ms == 'Y' or ms == 'y' and ms_maxattach <= int(smtp.esmtp_features['size']):
fromaddr = [ms_from]
toaddr = [ms_sendto]
cc = [ms_cc]
bcc = [ms_bcc]
msg = MIMEMultipart()
body = "\nYou're captured event is attached. \nThis is an automated email generated by Dumpcap.py"
msg.attach("From: %s\r\n" % fromaddr
+ "To: %s\r\n" % toaddr
+ "CC: %s\r\n" % ",".join(cc)
+ "Subject: %s\r\n" % ms_subject
+ "X-Priority = %s\r\n" % ms_importance
+ "\r\n"
+ "%s\r\n" % body
+ "%s\r\n" % ms_pm)
toaddrs = [toaddr] + cc + bcc
msg.attach(MIMEText(body, 'plain'))
filename = "dcdflts.cong"
attachment = open(filename, "rb")
if ms_attach == 'y' or ms_attach == "Y":
part = MIMEBase('application', 'octet-stream')
part.set_payload(attachment.read())
encoders.encode_base64(part)
part.add_header('Content-Disposition', "attachment; filename= %s" % filename)
msg.attach(part)
server = smtplib.SMTP(ms_smtp_server[ms_smtp_port])
server.starttls()
server.login(fromaddr, "YOURPASSWORD")
text = msg.as_string()
server.sendmail(fromaddr, toaddrs, text)
server.quit()
This is my second attempt, all "ms_..." variables are global through a larger program.
You shouldn't be reinventing the wheel. Use the mime modules Python has included in the standard library instead of trying to create the headers on your own. I haven't been able to test it out but check if this works:
import smtplib
import base64
import ConfigParser
from email.mime.application import MIMEApplication
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
filename = "test.pcapng"
with open(filename, 'rb') as fo:
filecontent = fo.read()
encoded_content = base64.b64encode(filecontent)
sender = 'notareal#email.com' # raw_input("Sender: ")
receiver = 'someother#fakeemail.com' # raw_input("Recipient: ")
marker = raw_input("Please input a unique set of numbers that will not be found elsewhere in the message, ie- roll face: ")
body ="""
This is a test email to send an attachment.
"""
message = MIMEMultipart(
From=sender,
To=receiver,
Subject='Sending Attachment')
message.attach(MIMEText(body)) # body of the email
message.attach(MIMEApplication(
encoded_content,
Content_Disposition='attachment; filename="{0}"'.format(filename)) # b64 encoded file
)
try:
smtpObj = smtplib.SMTP('smtp.gmail.com')
smtpObj.sendmail(sender, receiver, message)
print "Successfully sent email!"
except Exception:
print "Error: unable to send email"
I've left off a few parts (like the ConfigParser variables) and demonstrated only the email related portions.
References:
How to send email attachments with Python
Figured it out, with added ConfigParser. This is fully functional with a .ini file
import smtplib
####import sys#### duplicate
from email.parser import Parser
from email.mime.image import MIMEImage
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.base import MIMEBase
from email import encoders
import ConfigParser
def mail_man(cfg_file, event_file):
# Parse email configs from cfg file
Config = ConfigParser.ConfigParser()
Config.read(str(cfg_file))
mail_man_start = Config.get('DC_MS', 'ms')
security = Config.get('DC_MS', 'ms_security')
add_attachment = Config.get('DC_MS', 'ms_attach')
try:
if mail_man_start == "y" or mail_man_start == "Y":
fromaddr = Config.get("DC_MS", "ms_from")
addresses = [Config.get("DC_MS", "ms_sendto")] + [Config.get("DC_MS", "ms_cc")] + [Config.get("DC_MS", "ms_bcc")]
msg = MIMEMultipart() # creates multipart email
msg['Subject'] = Config.get('DC_MS', 'ms_subject') # sets up the header
msg['From'] = Config.get('DC_MS', 'ms_from')
msg['To'] = Config.get('DC_MS', 'ms_sendto')
msg['reply-to'] = Config.get('DC_MS', 'ms_replyto')
msg['X-Priority'] = Config.get('DC_MS', 'ms_importance')
msg['CC'] = Config.get('DC_MS', 'ms_cc')
msg['BCC'] = Config.get('DC_MS', 'ms_bcc')
msg['Return-Receipt-To'] = Config.get('DC_MS', 'ms_rrr')
msg.preamble = 'Event Notification'
message = '... use this to add a body to the email detailing event. dumpcap.py location??'
msg.attach(MIMEText(message)) # attaches body to email
# Adds attachment if ms_attach = Y/y
if add_attachment == "y" or add_attachment == "Y":
attachment = open(event_file, "rb")
# Encodes the attachment and adds it to the email
part = MIMEBase('application', 'octet-stream')
part.set_payload(attachment.read())
encoders.encode_base64(part)
part.add_header('Content-Disposition', "attachment; filename = %s" % event_file)
msg.attach(part)
else:
print "No attachment sent."
server = smtplib.SMTP(Config.get('DC_MS', 'ms_smtp_server'), Config.get('DC_MS', 'ms_smtp_port'))
server.ehlo()
server.starttls()
if security == "y" or security == "Y":
server.login(Config.get('DC_MS', 'ms_user'), Config.get('DC_MS', 'ms_password'))
text = msg.as_string()
max_size = Config.get('DC_MS', 'ms_maxattach')
msg_size = sys.getsizeof(msg)
if msg_size <= max_size:
server.sendmail(fromaddr, addresses, text)
else:
print "Your message exceeds maximum attachment size.\n Please Try again"
server.quit()
attachment.close()
else:
print "Mail_man not activated"
except:
print "Error! Something went wrong with Mail Man. Please try again."

SMTP sent mail to many recipients but doesn't received it

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.

Categories