I searched about this quite a lot, but could not fix the issue in my script. So finally, I decided to post it here.
Here's the code snippet:
fromaddr = "someValidAddress#xyz.com"
cc = ['SomeEmailAlias#xyz.com']
toaddr = ""
msg = MIMEMultipart()
toaddrlist = list(toaddr.split(',')) #As sendmail() accepts the list of recipients only in list form.
toaddrlist += (cc,)
msg['From'] = fromaddr
msg['To'] = toaddr
msg['Cc'] = ', '.join(cc)
msg['Date'] = formatdate(localtime=True)
msgHtml = MIMEText(html, 'html')
msg.attach(msgHtml)
msg['Subject'] = "Test mail"
server = "someMailServer.xyz.com"
smtp = smtplib.SMTP(server, 25)
smtp.sendmail(fromaddr, toaddrlist, msg.as_string())
smtp.close() #Close the SMTP server connection.
I'm aware and I've ensured that msg['To'] accepts a string value (toaddr), whereas toaddrlist in sendmail() should be a list.
Catch: If I remove the line toaddrlist += (cc,), then the mail does not get delivered twice to the recipients in "To" field, but the mail does not get delivered to the Cc alias.
Please help.
When the line toaddrlist += (cc,) is evaluated, the value of toaddrlist in your case is :
["", ["SomeEmailAlias#xyz.com"]]
and it's wrong because toaddrlist must be a list of strings not a list containing some lists.
So the solution is to change :
toaddrlist += (cc,)
to
toaddrlist += cc
or the recommended form (the pythonic way) :
toaddrlist.extend(cc)
Related
I would like to loop through a list and display each item on a separate line in my email.
The code works fine if I set body = "Just a string"
mylist = [first line,second line,third line,fourth line]
fromaddr = "EMAIL"
toaddr = "EMAIL"
msg = MIMEMultipart()
msg['From'] = fromaddr
msg['To'] = toaddr
msg['Subject'] = "EMAIL SUBJECT"
body = mylist
msg.attach(MIMEText(body, 'plain'))
server = smtplib.SMTP('smtp.gmail.com', 587)
server.ehlo()
server.starttls()
server.ehlo()
server.login("EMAIL", "PASSWORD")
text = msg.as_string()
server.sendmail(fromaddr, toaddr, text)
I tried just making body = to mylist just to see how it looked currently but I get the following error: _text.encode('us-ascii')
AttributeError: 'list' object has no attribute 'encode'
What I would like ultimately is the body of the email to look this (when I receive the email):
first line
second line
third line
fourth line
Thanks to Michael Butscher for the push in the right direction.
This does the job.
body = "\r\n".join(mylist)
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'm having big time problems with this issue-- another question on SO that didn't solve it is here: Send Raw Email (with attachment) to Multiple Recipients
My code (that works) is simple:
def send_amazon_email_with_attachment(html, subject, now, pre):
dummy = 'test#example.com'
recipients = ['test1#exampl.ecom', 'test2#example.com', 'test3#example.com']
connS3 = S3Connection('IDENTIFICATION','PASSWORD')
b = connS3.get_bucket('BUCKET_NAME')
key = b.get_key('FILE_NAME.pdf')
temp = key.get_contents_as_string()
msg = MIMEMultipart('alternative')
msg['Subject'] = subject
msg['From'] = 'My Name <test#example.com>'
msg.preamble = 'Multipart message.\n'
part1 = MIMEText(u"Attached is the report", 'plain')
part2 = MIMEText(html, 'html')
msg.attach(part1)
msg.attach(part2)
part = MIMEApplication(temp) #read binary
part.add_header('Content-Disposition', 'attachment', filename='FILE_NAME.pdf')
msg.attach(part)
conn = boto.ses.connect_to_region('us-east-1', aws_access_key_id='AUTH_ID', aws_secret_access_key='AUTH_PW')
for recipient in recipients:
print recipient
msg['To'] = recipient
result = conn.send_raw_email(msg.as_string(), source=msg['From'], destinations=recipient)
but, there's a caveat... this is looping for each recipient. Any variation of this does not work. Passing a list to msg['Bcc'] or msg['BCC'] will return an error that the list can't be stripped (same exact error as the posted question). Passing a string separated by commas gives an Amazon SES issue saying 'Illegal Email' in the returned XML. Because I only get an error from Amazon in specific situations, I'm led to believe this is an error with the program before it hits their API call.
Any MIMEMultipart experts have some ideas?
Basically you need to specify the email recipients in 2 different places using 2 different formats.
def send_amazon_email_with_attachment(html, subject, now, pre):
dummy = 'test#example.com'
recipients = ['test1#exampl.ecom', 'test2#example.com', 'test3#example.com']
connS3 = S3Connection('IDENTIFICATION','PASSWORD')
b = connS3.get_bucket('BUCKET_NAME')
key = b.get_key('FILE_NAME.pdf')
temp = key.get_contents_as_string()
msg = MIMEMultipart('alternative')
msg['Subject'] = subject
msg['From'] = 'My Name <test#example.com>'
msg['To'] = ', '.join(recipients)
msg.preamble = 'Multipart message.\n'
part1 = MIMEText(u"Attached is the report", 'plain')
part2 = MIMEText(html, 'html')
msg.attach(part1)
msg.attach(part2)
part = MIMEApplication(temp) #read binary
part.add_header('Content-Disposition', 'attachment', filename='FILE_NAME.pdf')
msg.attach(part)
conn = boto.ses.connect_to_region('us-east-1', aws_access_key_id='AUTH_ID', aws_secret_access_key='AUTH_PW')
result = conn.send_raw_email(msg.as_string(), source=msg['From'], destinations=recipients)
msg['To'] = ', '.join(recipients) isn't working for me (throws encoding error). Simply comment that line and your 'destinations' in "send_raw_email" should contain a list. That will work like a charm.
I am currently using Python 2.7 and trying to send a raw email with an attachment (CSV to be exact) to multiple addresses with Boto SES. I can send a normal email with send_email(), but I keep getting an error when trying to send to multiple people via send_raw_email().
This is the error that I get with a comma-separated string of recipients:
Error sending email: SESIllegalAddressError: 400 Illegal address
<ErrorResponse xmlns="http://ses.amazonaws.com/doc/2010-12-01/">
<Error>
<Type>Sender</Type>
<Code>InvalidParameterValue</Code>
<Message>Illegal address</Message>
</Error>
<RequestId>[the request ID]</RequestId>
</ErrorResponse>
That's from using this code:
to_emails = "me#example.com, them#example.com"
# create raw email
msg = MIMEMultipart()
msg['Subject'] = 'Email subject'
msg['From'] = 'me#example.com'
msg['To'] = to_emails
part = MIMEText('Attached is an important CSV')
msg.attach(part)
part = MIMEApplication(open(fname, 'rb').read())
part.add_header('Content-Disposition', 'attachment', filename=fname)
msg.attach(part)
# end create raw email
conn = boto.ses.connect_to_region(
'[my region]',
aws_access_key_id=s3_access_key,
aws_secret_access_key=s3_secret_key
)
conn.send_raw_email(msg.as_string(),
source=msg['From'],
destinations=msg['To']
)
Also, here is the error I get from using an array of strings for recipients:
Error sending email: 'list' object has no attribute 'lstrip'
It works fine if I have just one recipient, so it just throws the error when I have an array of recipients and a comma-separated string of recipients. Anyone have any experience with this?
I ended it getting it after looking at some docs and some more trial & error. It turns out that I just had to join the array of email strings for the msg['To'], and then I was able to pass in the email array for destinations parameter.
Here's what I did:
to_emails = "me#example.com, them#example.com"
COMMASPACE = ', '
# create raw email
msg = MIMEMultipart()
msg['Subject'] = 'Email subject'
msg['From'] = 'me#example.com'
msg['To'] = COMMASPACE.join(to_emails) ## joined the array of email strings
# edit: didn't end up using this ^
part = MIMEText('Attached is an important CSV')
msg.attach(part)
part = MIMEApplication(open(fname, 'rb').read())
part.add_header('Content-Disposition', 'attachment', filename=fname)
msg.attach(part)
# end create raw email
conn = boto.ses.connect_to_region(
'[my region]',
aws_access_key_id=s3_access_key,
aws_secret_access_key=s3_secret_key
)
conn.send_raw_email(msg.as_string(),
source=msg['From'],
destinations=to_emails ## passed in an array
)
I believe instead of a comma separated string with your recipients you have have to use a a list of strings.
Recipients = ['1#email.com', '2#email.com']
conn.send_raw_email(msg.as_string(),
source=msg['From'],
destinations= Recipients)
So something along those lines.
Source: http://boto.readthedocs.org/en/latest/ref/ses.html?highlight=send_raw_email#boto.ses.connection.SESConnection.send_raw_email
The official documentation says a list of strings or simply a string. This is why it works with only one recipient.
Second attempt::
to_emails = ['me#example.com', 'them#example.com']
# create raw email
msg = MIMEMultipart()
msg['Subject'] = 'Email subject'
msg['From'] = 'me#example.com'
msg['To'] = to_emails
conn.send_raw_email(msg.as_string(),
source=msg['From'],
destinations=msg['To'])
Am I right in assuming your code now looks like this? If not, try this.
The solution is set a string separated by comma to the header and a list to destinations field.
Something like:
to_emails = ['me#example.com', 'them#example.com']
msg['To'] = ', '.join( to_emails )
and
...
conn.send_raw_email(msg.as_string(),
source=msg['From'],
destinations=to_emails ## passed in an array
)
When sending without attachment just assigning list works. But in other case the below code helped..Thanks #Ezequiel Salas
to_emails = ['me#example.com', 'them#example.com']
or
to_emails = some_list
msg['To'] = ', '.join( to_emails )
I am trying to use the MIME and send the email using the following code. But the python is not able to change the value of the msg['Subject']. What I am doing wrong? Any suggestions?
Thanks
msg = MIMEText('MAIL from my python programme')
msg['Subject'] = 'Testing '
msg['From'] = USERNAME
msg['To'] = MAILTO
test_var=1
if(test_var):
msg['Subject'] = 'Test variable is 1'
else:
msg['Subject'] = 'Test variable is 0'
server = smtplib.SMTP('smtp.gmail.com:587')
server.ehlo_or_helo_if_needed()
server.starttls()
server.ehlo_or_helo_if_needed()
server.login(USERNAME,PASSWORD)
server.sendmail(USERNAME, MAILTO, msg.as_string())
server.quit()
print "sending email"
From what I can tell, you have to delete the Subject field (or any other) before you replace it. Otherwise, it just appends more subjects - which might be ignored, looking like the value doesn't change.
test_var=1
del msg['Subject']
if(test_var):
msg['Subject'] = 'Test variable is 1'
else:
msg['Subject'] = 'Test variable is 0'