Related
I'm building a mail sender which I want to take one email at a time and not add all the receipents into BCC.
So, with the code below I'm trying to make it add one email at a time from the .xlsx list, add it to "TO" and send the email, and then repeat on the next row in the .xlsx-file.
I have a code that looks like this:
import pandas as pd
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
import smtplib
email_list = pd.read_excel('/home/xxxx/test.xlsx')
emails = email_list['EMAIL']
email_list['EMAIL'] = email_list.index
my_list = email_list['EMAIL'].tolist()
print(my_list)
msg = MIMEMultipart()
msg['From'] = "test#xxxx.com"
msg['To'] = ",".join(str(my_list))
msg['Subject'] = "This is the subject"
message = """
<html><p>randomtext</p></html>
"""
message2 = "plain text msg"
msg.attach(MIMEText(message,'html'))
msg.attach(MIMEText(message2,'plain'))
Password = "thisispassword"
server = smtplib.SMTP('smtp.mail.com:587')
#server.ehlo()
server.starttls()
server.login(msg['From'],Password)
server.sendmail(msg['From'],msg['To'],msg.as_string())
server.quit()
Instead I get the following error:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/home/seniori/anaconda3/lib/python3.8/smtplib.py", line 885, in sendmail
raise SMTPRecipientsRefused(senderrs)
smtplib.SMTPRecipientsRefused: {'[,0,,, ,1,,, ,2,]': (501, b'<[,0,,, ,1,,,=,2,]>: missing or malformed local part')}
It seems like it is finding the rows in the excel-file but not the email adresses.
Any idea of what I need to change here?
EDIT: Here is the total error log
Type "help", "copyright", "credits" or "license" for more information.
>>> import pandas as pd
>>>
>>> from email.mime.multipart import MIMEMultipart
>>> from email.mime.text import MIMEText
>>> import smtplib
>>>
>>> email_list = pd.read_excel('/home/xxxxx/test.xlsx')
>>>
>>> emails = email_list['EMAIL']
>>> email_list['EMAIL'] = email_list.index
>>>
>>> my_list = email_list['EMAIL'].tolist()
>>> print(my_list)
[0, 1, 2]
>>>
>>>
>>> msg = MIMEMultipart()
>>> msg['From'] = "mail#example.org"
>>> msg['To'] = ",".join(str(my_list))
>>> msg['Subject'] = "subject"
>>>
>>> message = """
... <html><p>randomtext</p></html>
... """
>>> message2 = "plain text msg"
>>> msg.attach(MIMEText(message,'html'))
>>> msg.attach(MIMEText(message2,'plain'))
>>> Password = "Wenglish2.1"
>>> server = smtplib.SMTP('mail#example.org')
[proxychains] Dynamic chain ... 127.0.0.1:9050 ... 127.0.0.1:9050 <--denied
[proxychains] Dynamic chain ... 127.0.0.1:9050 ... mail#example.org:587 ... OK
>>> #server.ehlo()
>>> server.starttls()
(220, b'TLS go ahead')
>>> server.login(msg['From'],Password)
(235, b'Authentication succeeded')
>>> server.sendmail(msg['From'],msg['To'],msg.as_string())
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/home/seniori/anaconda3/lib/python3.8/smtplib.py", line 885, in sendmail
raise SMTPRecipientsRefused(senderrs)
smtplib.SMTPRecipientsRefused: {'[,0,,, ,1,,, ,2,]': (501, b'<[,0,,, ,1,,,=,2,]>: missing or malformed local part')}
>>>
>>> server.quit()
(221, b'xxxx.xxxx.com closing connection')
>>>
And the email list is in a UTF-8 excel .xlsx-file that looks like this:
EMAIL
test#gmail.com
test1#gmail.com
test2#gmail.com
I've sorted it out by doing the following:
for i in range(0,len(emails)):
msg['To'] = my_list[i]
server.sendmail(msg['From'],msg['To'],msg.as_string())
del msg['To']
This is making a loop and sending one email at a time from the excel-sheet.
STMP.sendmail expects the to_addrs argument to be a list:
... list of RFC 822 to-address strings (a bare string will be treated as a list with 1 address)
The TO header in the mail body can (must) be a comma-separated string, but the argument to sendmail must be a list.
So you code should be
server.sendmail(msg['From'], mylist, msg.as_string())
Summary:
I will try to explain in my first pass but if I am missing some pertinent detail let me know and I will follow up on it. I am ingesting a list of servers from a text file and using pyopenssl to resolve, connect,and retrieve the SSL Certificate information. Based on the expire date I am calculating the number of days before the cert expires. My results are passed through an array, formatted, and then sent in an email.
It is working perfectly until one of my servers does not resolve and I get the socket.gaierror.
Problem: When the host does not resolve it blows up my results and I am getting the error below. Although it logs the error correctly I am trying pass along something that will note the exception in my results in the format of host, hostname, expiration date, and days to expire that I will be able to pass to the table and send in an email. I want it to note in the host field "Unable to resolve" and maybe just "0" as a result for expiration date and days to expire. Can anyone point me towards a good way of accomplishing that? Thanks!
Error Message:
Checking certificate for server server.domain.com
--- Logging error ---
Traceback (most recent call last):
File "ssl_nag_script_test.py", line 80, in <module>
s.connect((host, int(port)))
socket.gaierror: [Errno 11001] getaddrinfo failed.
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "E:\Python36\lib\logging\__init__.py", line 992, in emit
msg = self.format(record)
File "E:\Python36\lib\logging\__init__.py", line 838, in format
return fmt.format(record)
File "E:\Python36\lib\logging\__init__.py", line 575, in format
record.message = record.getMessage()
File "E:\Python36\lib\logging\__init__.py", line 338, in getMessage
msg = msg % self.args
TypeError: not all arguments converted during string formatting
Call stack:
File "ssl_nag_script_test.py", line 106, in <module>
logger.warning('Error on connection to Server,', str(ip))
Message: 'Error on connection to Server,'
Arguments: ('server.domain.com:443\n',)
--- Logging error ---
Traceback (most recent call last):
File "ssl_nag_script_test.py", line 80, in <module>
s.connect((host, int(port)))
socket.gaierror: [Errno 11001] getaddrinfo failed.
**Then**
WARNING:root:ERROR ENCOUNTERED!
WARNING:root:Traceback (most recent call last):
File "ssl_nag_script - Copy.py", line 114, in <module>
key=lambda k: k[1]['days_to_expire'], reverse=False)
TypeError: '<' not supported between instances of 'str' and 'int'
Python Code
# Import the basic modules to run this script
import ssl
from datetime import datetime
import OpenSSL
import socket
from datetime import timedelta
import datetime
import traceback
import logging
# Import the needed libs for sending smtp emails
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.base import MIMEBase
from email import encoders
# Set variables for email
email_sen = 'sen#email.com'
email_rec = 'rec#email.com'
subject = 'SSL Certificate Results'
# Create message container for email
msg = MIMEMultipart('alternative')
msg['From'] = email_sen
msg['To'] = email_rec
msg['Subject'] = subject
# Setup logging
logger = logging.getLogger(__name__)
logger.setLevel(logging.WARNING)
formatter = logging.Formatter('%(asctime)s:%(levelname)s:%(message)s')
file_handler = logging.FileHandler('log/SSLNag.log')
file_handler.setFormatter(formatter)
logger.addHandler(file_handler)
try:
# opening file with list of servers and set date and time
ipfile = open('server_ip.txt')
cur_date = datetime.datetime.utcnow()
# Create an array to house the results.
# Array will have sub arrays in the format of [host ip] = {host, hostname, expiration date, days to expire}
ssl_results = {}
except Exception as e:
logger.warning("ERROR ENCOUNTERED! \n\n")
logger.warning(str(traceback.format_exc()))
# scan each host in the ip file and check it's ssl
for ip in ipfile:
# Record an entry in the ssl_resutls array
# Always default to false
ssl_results[str(ip)] = {'host': '', 'server_name': '', 'exp_date': '', 'days_to_expire': ''}
try:
host = ip.strip().split(':')[0]
port = ip.strip().split(':')[1]
print('\nChecking certifcate for server ', host)
# Connect to server using SSL.
ctx = OpenSSL.SSL.Context(ssl.PROTOCOL_TLSv1)
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host, int(port)))
cnx = OpenSSL.SSL.Connection(ctx, s)
cnx.set_connect_state()
cnx.do_handshake()
# Connection complete get SSL certificate and close connection.
cert = cnx.get_peer_certificate()
s.close()
# From SSL certificate get host name, expiration date and decode.
server_name = cert.get_subject().commonName
print(server_name)
edate = cert.get_notAfter()
edate = edate.decode()
# Get date and format. Calculate number of days until SSL expires.
exp_date = datetime.datetime.strptime(edate, '%Y%m%d%H%M%SZ')
days_to_expire = int((exp_date - cur_date).days)
print(exp_date)
print('day to expire', days_to_expire)
# Update the hosts entry
ssl_results[str(ip)]['host'] = host
ssl_results[str(ip)]['server_name'] = server_name
ssl_results[str(ip)]['exp_date'] = exp_date
ssl_results[str(ip)]['days_to_expire'] = days_to_expire
# Logging for errors
except Exception as e:
logger.warning('Error on connection to Server,', str(ip))
logger.warning("ERROR ENCOUNTERED", host, "\n\n")
logger.warning(str(traceback.format_exc()))
# Loop through the ssl_results entries and generate a email + results file
try:
# Sort the ssl_results
sorted_results = sorted(ssl_results.items(),
key=lambda k: k[1]['days_to_expire'], reverse=False)
# variable to hold html for email
SSLCertificates = """<html>
<head>
<style>
table{width: 1024px;}
table, th, td {
border: 1px solid black;
border-collapse: collapse;
}
th, td {
padding: 5px;
text-align: left;
}
ul:before{
content:attr(data-header);
font-size:120%;
font-weight:bold;
margin-left:-15px;
}
</style>
</head>
<body>
<p><h2>Hello, </h2>
<h3>SSL Expiration Summary:</h3>
<span style="color:red;"><b>NOTE: If any of the below SSL certificates have less than 90 days remaining please renew.<b></span><br><br>
<table id=\"exp_ssls\"><tr><th>Host</th><th>Hostname</th><th>Expiration Date</th><th>Remaining Days</th></tr>
"""
# Write results in an html table
# Apply this formatting if days to expire are equal to or less than 90 days
for server, data in sorted_results:
if float(str(data["days_to_expire"])) <= 90:
SSLCertificates += "<tr><td bgcolor=yellow><font color=red><b>" + str(server) + "</b></td><td bgcolor=yellow><font color=red><b>" + str(data["server_name"]) + "</b></td><td bgcolor=yellow><font color=red><b>" + str(
data["exp_date"]) + "</b></td><td bgcolor=yellow><font color=red><b>" + str(data["days_to_expire"]) + "</b></td></tr>"
# Apply this formatting if days to expire are equal to or greater than 91 days
if float(str(data["days_to_expire"])) >= 91:
SSLCertificates += "<tr><td>" + str(server) + "</td><td>" + str(data["server_name"]) + "</td><td>" + str(
data["exp_date"]) + "</td><td>" + str(data["days_to_expire"]) + "</td></tr>"
SSLCertificates += """</body>
</html>"""
# Write data to a file and attach it to the email
f = open('SSLCertificates.html', 'w')
f.write(SSLCertificates)
f.close()
filename = 'SSLCertificates.html'
attachment = open(filename, 'rb')
# Setup email attachment
msg.attach(MIMEText(SSLCertificates, 'html'))
part = MIMEBase('application', 'octet-stream')
part.set_payload(attachment.read())
encoders.encode_base64(part)
part.add_header('Content-Disposition', "attachment; filename=" + filename)
# Send email
msg.attach(part)
text = msg.as_string()
server = smtplib.SMTP('smtp.server.com', 25)
server.sendmail(email_sen, email_rec, text)
server.quit()
# Logging for errors
except Exception as e:
logging.warning("ERROR ENCOUNTERED! \n\n")
logging.warning(str(traceback.format_exc()))
You have
logger.warning('Error on connection to Server,', str(ip))
but it should be:
logger.warning('Error on connection to Server "%s"', str(ip))
or equivalent.
You are passing an extra parameter str(ip) but there is no placeholder in the message to put it, hence the following part of your error:
File "E:\Python36\lib\logging\__init__.py", line 338, in getMessage
msg = msg % self.args
TypeError: not all arguments converted during string formatting
Call stack:
File "ssl_nag_script_test.py", line 106, in <module>
logger.warning('Error on connection to Server,', str(ip))
I am trying to obtain a result set from SQL query and add it to my email template which is an HTML file.
Two Functions:
One for mail summary and the other one to change the email body.
I am using smtplib and email packages from python to send out a mail.
#send a email
from fileOps import fileOps
from dbOps import dbOps
import smtplib
from smtplib import SMTP, SMTPException
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
mailFrom = ''
password = ''
mailTo = ''
mailServer = 'smtp.gmail.com'
port = 587
s = smtplib.SMTP(mailServer,port)
#function for email summary
def emailSummary():
try:
#security
s.starttls()
s.login(mailFrom,password)
#for fetching all the records
dbObj = dbOps()
db = dbObj.connectDB()
sql = "SELECT DISTINCT CASE_MASTER.AGREEMENTID, CASE_MASTER.NO_OF_FILES FROM " \
"CASE_MASTER LEFT JOIN CASE_FILE_STATUS ON CASE_FILE_STATUS.MOVED_TO_AWS_FLAG = CASE_MASTER.MOVED_TO_AWS_FLAG " \
"AND CASE_FILE_STATUS.MOVED_TO_AWS_Date AND CASE_MASTER.MOVED_TO_AWS_FLAG IS NOT NULL " \
"WHERE CASE_FILE_STATUS.MOVED_TO_AWS_FLAG = 1 AND CASE_FILE_STATUS.MOVED_TO_AWS_Date IS NOT NULL"
resultSet = dbObj.readData(db, sql)
getEmailBody(resultSet)
emailBody = getEmailBody(resultSet)
s.sendmail(mailFrom, mailTo,emailBody)
s.quit()
# print("Email Successfully sent !!! ")
except smtplib.SMTPException as e :
print(e)
#function to get emailBody
def getEmailBody(resultSet):
try:
htmlTemplate = open('summaryTemplate.html', 'r')
alert_msg = MIMEText(htmlTemplate.read(), "html", "utf-8")
html = htmlTemplate.read()
part1 = MIMEText(html, 'html')
part2 = """<table>
% for r in resultSet:
<tr>
% for cell in r:
<td>${cell}</td>
% endfor</tr>
% endfor</table>""".format(**locals())
msg = MIMEMultipart('alternative')
msg['Subject'] = "HERO_FC_DM_DB"
msg['From'] = mailFrom
msg['To'] = mailTo
msg.attach(part1)
except Exception as e:
print(e)
emailSummary()
I am getting the row but not getting the content from that row
['81173'] 'cell'
File "C:\Users\sailee.pawar\AppData\Local\Programs\Python\Python37-32\lib\smtplib.py", line 858, in sendmail
esmtp_opts.append("size=%d" % len(msg))
'cell'
TypeError: object of type 'NoneType' has no len()
I am getting the above error
Traceback (most recent call last):
line 68, in emailSummary()
line 37, in emailSummary
s.sendmail(mailFrom, mailTo,emailBody)
line 858, in sendmail esmtp_opts.append("size=%d" % len(msg))
'cell'
TypeError: object of type 'NoneType' has no len()
expected o/p :
['81173']
'file1.jpg'
'file2.txt'
I want to write a program that sends email using Python's smtplib. I searched through the document and the RFCs, but couldn't find anything related to attachments. Thus, I'm sure there's some higher-level concept I'm missing out on. Can someone clue me in on how attachments work in SMTP?
Here is an example of a message with a PDF attachment, a text "body" and sending via Gmail.
# Import smtplib for the actual sending function
import smtplib
# For guessing MIME type
import mimetypes
# Import the email modules we'll need
import email
import email.mime.application
# Create a text/plain message
msg = email.mime.Multipart.MIMEMultipart()
msg['Subject'] = 'Greetings'
msg['From'] = 'xyz#gmail.com'
msg['To'] = 'abc#gmail.com'
# The main body is just another attachment
body = email.mime.Text.MIMEText("""Hello, how are you? I am fine.
This is a rather nice letter, don't you think?""")
msg.attach(body)
# PDF attachment
filename='simple-table.pdf'
fp=open(filename,'rb')
att = email.mime.application.MIMEApplication(fp.read(),_subtype="pdf")
fp.close()
att.add_header('Content-Disposition','attachment',filename=filename)
msg.attach(att)
# send via Gmail server
# NOTE: my ISP, Centurylink, seems to be automatically rewriting
# port 25 packets to be port 587 and it is trashing port 587 packets.
# So, I use the default port 25, but I authenticate.
s = smtplib.SMTP('smtp.gmail.com')
s.starttls()
s.login('xyz#gmail.com','xyzpassword')
s.sendmail('xyz#gmail.com',['xyz#gmail.com'], msg.as_string())
s.quit()
Here's an example I snipped out of a work application we did. It creates an HTML email with an Excel attachment.
import smtplib,email,email.encoders,email.mime.text,email.mime.base
smtpserver = 'localhost'
to = ['email#somewhere.com']
fromAddr = 'automated#hi.com'
subject = "my subject"
# create html email
html = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" '
html +='"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml">'
html +='<body style="font-size:12px;font-family:Verdana"><p>...</p>'
html += "</body></html>"
emailMsg = email.MIMEMultipart.MIMEMultipart('alternative')
emailMsg['Subject'] = subject
emailMsg['From'] = fromAddr
emailMsg['To'] = ', '.join(to)
emailMsg['Cc'] = ", ".join(cc)
emailMsg.attach(email.mime.text.MIMEText(html,'html'))
# now attach the file
fileMsg = email.mime.base.MIMEBase('application','vnd.ms-excel')
fileMsg.set_payload(file('exelFile.xls').read())
email.encoders.encode_base64(fileMsg)
fileMsg.add_header('Content-Disposition','attachment;filename=anExcelFile.xls')
emailMsg.attach(fileMsg)
# send email
server = smtplib.SMTP(smtpserver)
server.sendmail(fromAddr,to,emailMsg.as_string())
server.quit()
What you want to check out is the email module. It lets you build MIME-compliant messages that you then send with smtplib.
Well, attachments are not treated in any special ways, they are "just" leaves of the Message-object tree. You can find the answers to any questions regarding MIME-compliant mesasges in this section of the documentation on the email python package.
In general, any kind of attachment (read: raw binary data) can be represented by using base64
(or similar) Content-Transfer-Encoding.
Here's how to send e-mails with zip file attachments and utf-8 encoded subject+body.
It was not straightforward to figure this one out, due to lack of documentation and samples for this particular case.
Non-ascii characters in replyto needs to be encoded with, for instance, ISO-8859-1. There probably exists a function that can do this.
Tip:Send yourself an e-mail, save it and examine the content to figure out how to do the same thing in Python.
Here's the code, for Python 3:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# vim:set ts=4 sw=4 et:
from os.path import basename
from smtplib import SMTP
from email.mime.text import MIMEText
from email.mime.base import MIMEBase
from email.mime.multipart import MIMEMultipart
from email.header import Header
from email.utils import parseaddr, formataddr
from base64 import encodebytes
def send_email(recipients=["somebody#somewhere.xyz"],
subject="Test subject æøå",
body="Test body æøå",
zipfiles=[],
server="smtp.somewhere.xyz",
username="bob",
password="password123",
sender="Bob <bob#somewhere.xyz>",
replyto="=?ISO-8859-1?Q?M=F8=F8=F8?= <bob#somewhere.xyz>"): #: bool
"""Sends an e-mail"""
to = ",".join(recipients)
charset = "utf-8"
# Testing if body can be encoded with the charset
try:
body.encode(charset)
except UnicodeEncodeError:
print("Could not encode " + body + " as " + charset + ".")
return False
# Split real name (which is optional) and email address parts
sender_name, sender_addr = parseaddr(sender)
replyto_name, replyto_addr = parseaddr(replyto)
sender_name = str(Header(sender_name, charset))
replyto_name = str(Header(replyto_name, charset))
# Create the message ('plain' stands for Content-Type: text/plain)
try:
msgtext = MIMEText(body.encode(charset), 'plain', charset)
except TypeError:
print("MIMEText fail")
return False
msg = MIMEMultipart()
msg['From'] = formataddr((sender_name, sender_addr))
msg['To'] = to #formataddr((recipient_name, recipient_addr))
msg['Reply-to'] = formataddr((replyto_name, replyto_addr))
msg['Subject'] = Header(subject, charset)
msg.attach(msgtext)
for zipfile in zipfiles:
part = MIMEBase('application', "zip")
b = open(zipfile, "rb").read()
# Convert from bytes to a base64-encoded ascii string
bs = encodebytes(b).decode()
# Add the ascii-string to the payload
part.set_payload(bs)
# Tell the e-mail client that we're using base 64
part.add_header('Content-Transfer-Encoding', 'base64')
part.add_header('Content-Disposition', 'attachment; filename="%s"' %
os.path.basename(zipfile))
msg.attach(part)
s = SMTP()
try:
s.connect(server)
except:
print("Could not connect to smtp server: " + server)
return False
if username:
s.login(username, password)
print("Sending the e-mail")
s.sendmail(sender, recipients, msg.as_string())
s.quit()
return True
def main():
send_email()
if __name__ == "__main__":
main()
# -*- coding: utf-8 -*-
"""
Mail sender
"""
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
import smtplib
import pystache
import codecs
import time
import sys
reload(sys)
sys.setdefaultencoding('utf-8')
HOST = 'smtp.exmail.qq.com'
PORT = 587
USER = 'your#mail.com'
PASS = 'yourpass'
FROM = 'your#mail.com'
SUBJECT = 'subject'
HTML_NAME = 'tpl.html'
CSV_NAME = 'list.txt'
FAILED_LIST = []
def send(mail_receiver, mail_to):
# text = mail_text
html = render(mail_receiver)
# msg = MIMEMultipart('alternative')
msg = MIMEMultipart('mixed')
msg['From'] = FROM
msg['To'] = mail_to.encode()
msg['Subject'] = SUBJECT.encode()
# msg.attach(MIMEText(text, 'plain', 'utf-8'))
msg.attach(MIMEText(html, 'html', 'utf-8'))
try:
_sender = smtplib.SMTP(
HOST,
PORT
)
_sender.starttls()
_sender.login(USER, PASS)
_sender.sendmail(FROM, mail_to, msg.as_string())
_sender.quit()
print "Success"
except smtplib.SMTPException, e:
print e
FAILED_LIST.append(mail_receiver + ',' + mail_to)
def render(name):
_tpl = codecs.open(
'./html/' + HTML_NAME,
'r',
'utf-8'
)
_html_string = _tpl.read()
return pystache.render(_html_string, {
'receiver': name
})
def main():
ls = open('./csv/' + CSV_NAME, 'r')
mail_list = ls.read().split('\r')
for _receiver in mail_list:
_tmp = _receiver.split(',')
print 'Mail: ' + _tmp[0] + ',' + _tmp[1]
time.sleep(20)
send(_tmp[0], _tmp[1])
print FAILED_LIST
main()
I'm trying to send an email with an attachment from my local machine to a gmail account.
Here's my code:
import smtplib
from os.path import basename
from email.mime.application import MIMEApplication
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.utils import COMMASPACE, formatdate
from email import Encoders
def send_mail(send_from, send_to, body, text, files=None,server="127.0.0.1"):
try:
assert isinstance(send_to, list)
except AssertionError as e:
print e
msg = MIMEMultipart(
From=send_from,
To=COMMASPACE.join(send_to),
Date=formatdate(localtime=True),
Subject=body
)
msg.attach(MIMEText(text))
for f in files or []:
with open(f, "rb") as fil:
msg.attach(MIMEApplication(fil.read(), Content_Disposition='attachment; filename="%s"' % basename(f)))
try:
smtp = smtplib.SMTP(server)
smtp.sendmail(send_from, send_to, msg.as_string())
print "Successfully sent mail."
except SMTPException:
print "Error: unable to send email"
smtp.close()
Based on the accepted answer of this question.
And here's the code that calls it:
send_from = "name.surname#my-company.com"
send_to = "lcuky_recipient#gmail.com"
subject = "testEmail",
text = "This is a test. Hopefully, there's a file attached to it."
files = ".././dudewhat.csv"
send_mail(send_from, send_to, subject, text, files)
But this is what I'm getting in return:
File "belo_monthly.py", line 138, in <module>
send_mail(send_from, send_to, subject, text, files)
File "belo_monthly.py", line 26, in send_mail
Subject=body
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/email/mime/multipart.py", line 36, in __init__
MIMEBase.__init__(self, 'multipart', _subtype, **_params)
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/email/mime/base.py", line 25, in __init__
self.add_header('Content-Type', ctype, **_params)
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/email/message.py", line 408, in add_header
parts.append(_formatparam(k.replace('_', '-'), v))
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/email/message.py", line 52, in _formatparam
value = utils.encode_rfc2231(value[2], value[0], value[1])
IndexError: tuple index out of range
What did I miss?
this is your problem:
subject = "testEmail",
remove comma at the end and things should work
You are checking for instance for list but the parsed value is string. Try changing
send_to = "lcuky_recipient#gmail.com"
to
send_to = ["lcuky_recipient#gmail.com"]
or modify the logic