I created a script in python to email with an attachment. I put it in databricks, and put it on a schedule. When I manually run this function, it fires only one email, but when it runs on the schedule, to emails are sent to each recipient. Although it sounds like a schedule issue, I believe it's a code issue - I was able to get it to work at some point, but now it is sending again.
If anyone can take a look at the code below and see if they can figure out why it would be duplicating, it would be appreciated!
from email.mime.image import MIMEImage
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.application import MIMEApplication
from datetime import date
def SendEmail(recipient, subject,message_records,attach,cc,bcc,df):
server = smtplib.SMTP ('smtp.sendgrid.net', 587) # check server and port with your provider
server.ehlo()
server.starttls()
server.login("apikey", dbutils.secrets.get(scope = "XXXX", key = "XXXX")) # insert secret name
sender = dbutils.secrets.get(scope = "XXXX", key = "XXXX") # insert secret name
msg = MIMEMultipart()
msg['Subject'] = subject
msg['From'] = "noreply#noreply.com"
msg['cc'] = ", ".join([cc])
msg['To'] = recipient
rcpt = bcc.split(",") +cc.split(",") + [recipient]
message = """
<html>
<body>
Good morning, <br> <br>
"""+message_records+"""<br> <br>
Thank you and have a wonderful day!
</body>
</html>
"""
if attach==1:
msg.attach(MIMEText(message,'html'))
filename = "ASN-" + str(date.today())+'.csv'
attachment = MIMEApplication(df.to_csv(index=False))
attachment["Content-Disposition"] = 'attachment; filename=" {}"'.format(filename)
msg.attach(attachment)
else:
msg.attach(MIMEText(message,'html'))
server.sendmail(sender, rcpt, msg.as_string())
server.close()```
I suggest you look at the SENDGRID library for python. It uses the API key that you get from the service and it is built just for this service.
https://docs.sendgrid.com/for-developers/sending-email/v3-python-code-example
See if this code produces the same duplicate issue you are seeing.
If I remember right, send grid keeps track of the sent mail messages. Make sure the "to - recipient" list does not have duplicate addresses.
I do not see any obvious issues with the above code.
Here is the PyPi link. There are a ton of examples on usage.
https://pypi.org/project/sendgrid/
Related
I'm trying to send emails to people in a distribution list in my company using python. My company uses outlook.
When I send to individual users specifying their email, it works perfectly. However I need to use the distribution list, since the recipients are updated by my IT department and I cant keep updating the email list whenever it changes.
Whomever has used outlook, you might recall that the distribution list starts with an exclamation mark like so: !groupdept#company.com
I am using the following method to send emails using python:
from email.mime.text import MIMEText
from email.mime.application import MIMEApplication
from email.mime.multipart import MIMEMultipart
from smtplib import SMTP
import smtplib
import sys
subject = "Group Email"
fromm = 'me#company.com'
recipients = ['someone#company.com, someonelse#company.com']
emaillist = [elem.strip().split(',') for elem in recipients]
msg = MIMEMultipart()
msg['Subject'] = subject
msg['From'] = fromm
html = """\
<html>
<head>
</head>
<body style="font-size:18px;">
{0}
</body>
</html>
""".format(df2.style
.set_properties(**{'border': '2.5pt solid green', 'color': 'magenta', 'font-size': '15pt'})
.hide_index()
.hide_columns()
.render()
)
message = MIMEText(html, 'html')
msg.attach(message)
server = smtplib.SMTP('00.0.0.00', 25)
server.sendmail(msg['From'], emaillist , msg.as_string())
The above method works well for comma separated recipients. However if I use !groupdept#company.com it doesn't work, which I can understand since that is an MS Outlook functionality.
Has anyone achieved this before?
I want to make a script that sends my homework to my mail every now and then, but they sending a mail part isn't working. I have looked at tutorials, but I still get a mistake when i write
msg = MIMEMultipart()
Is there something wrong with that?
(I use gmail)
for name, email in zip(names, emails):
print("Writing the mail")
msg = MIMEMultipart()
# add in the actual person name to the message template
message = message_template.substitute(PERSON_NAME=name.title())
# setup the parameters of the message
msg['From']=Myaddress
msg['To']=email
msg['Subject']="Homework"
# add in the message body
msg.attach(MIMEText(message, 'plain'))
# send the message via the server set up earlier.
s.send_message(msg)
print("Mail sent")
del msg
btw I have multiple mails to send it to.
And yes I imported these:
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
I am trying to send auto generated mail with attachment for a list of recipiant.I have written one class Mail like this:-
Its sending mail with proper data but sometime some recipiant are not getting mail in proper time and some are getting mail when i run this file.Those guys who are not getting the mail in proper time are getting the same mail after a lot of time.(it depends 1hr-10hr).
Don't know whats the problem ?
Is there any restriction for perticular domain or perticular id? like i can send only 5 or 10 auto generated mail within 1hr or 2 hr?
class Mail:
def send_mail(self,recipient,message,filepath):
import smtplib
from email.MIMEMultipart import MIMEMultipart
from email.MIMEText import MIMEText
Userid = 'mail#domain.in'
Password = 'password'
for rec in recipient:
msg = MIMEMultipart()
msg['From'] = 'no-reply#test.in'
msg['To'] = rec
msg['Subject'] = "Daily Mail"
msg.attach(MIMEText(message))
f = file(filepath)
attachment = MIMEText(f.read())
attachment.add_header('Content-Disposition', 'attachment', filename='download file')
msg.attach(attachment)
mailServer = smtplib.SMTP('smtpauth.mydomain.in', 587)
mailServer.ehlo()
#mailServer.starttls()
mailServer.ehlo()
mailServer.login(Userid, Password)
mailServer.sendmail(Userid, rec, msg.as_string())
mailServer.close()
here i am trying to send the mail:-
m = Mail()
m.send_mail(['mail1#gmail.com','mail2#somedomain.in','mail3#otherdomain.in','mail4#gmail.com'],'helloooooooo','C:/Office/file/myfile.xlsx')
Yes there might be limitations both on your "smtpauth.mydomain.in" mail server and on the receiving mail servers.
Multiple identical mails from one sender to a lot of different destinations might get stuck in different spam filters.
To get the exact limitations of how often you can send mails I guess you have to ask your mail service provider.
I'm trying to learn python from a book ("Hello! Python"). This code should, according to the book, send an email. no luck so far.
import os
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
import smtplib
def send_message(message):
s = smtplib.SMTP('smtp.me.com')
s.sendmail(message['From'], message['To'], message.as_string())
s.quit()
def mail_report(to, ticker_name):
outer = MIMEMultipart()
outer['Subject'] = "Stock report for " + ticker_name
outer['From'] = "myemail#mac.com"
outer['To'] = to
# Internal text container
inner = MIMEMultipart('alternative')
text = "Here is the stock report for " + ticker_name
html = """\
<html>
<head></head>
<body>
<p>Here is teh stock report for
<b> """ + ticker_name + """ </b>
</p>
</body>
</html>
"""
part1 = MIMEText(text, 'plain')
part2 = MIMEText(html, 'html')
inner.attach(part1)
inner.attach(part2)
outer.attach(inner)
filename = 'stocktracker-%s.csv' % ticker_name
csv_text = ''.join(file(filename).readlines())
csv_part = MIMEText(csv_text, 'csv')
csv_part.add_header('Content-Disposition', 'attachment', filename=filename), outer.attach(csv_part)
return outer
if __name__ == '__main__':
email = mail_report('myemail#mac.com', 'GOOG')
send_message(email)
I don't get an error, but I also don't get an email. (needless to say, i'm using my actual email, not 'myemail#mac.com') All suggestions and suggested reading appreciated.
You can run a local smtp debugging server. Find where smtpd.py is located, then run the command:
$ python /usr/lib/python2.7/smtpd.py -n -c DebuggingServer localhost:8025
Then on a second terminal screen run the Python interpreter:
>>> import smtplib
>>> s = smtplib.SMTP('localhost', 8025)
>>> s.sendmail('me', 'you', 'Hi!')
You should see 'Hi!' in the first screen.
smtplib.sendmail should eventually raise an exception if it can't send the mail - it may just take a while for the timeout due to the connection being dropped by a firewall. Give it a few minutes. Meanwhile, read below about what could be going wrong.
The code tries to directly connect to smtp.me.com and send mail via SMTP (port 25). This will only work if:
Your internet setup lets you make outgoing connections on port 25
smtp.me.com listens on port 25 (it does)
the recipient email is a valid address ending in #mac.com (myemail#mac.com is not valid: 550 5.1.1 unknown or illegal alias: myemail#mac.com
)
smtp.me.com still processes emails for #mac.com (Mobile Me was shut down in favor of iCloud some time ago, so I'm not sure the #mac.com addresses are still valid)
You can substitute any other mail server for smtp.me.com, preferably that of your ISP, which should be willing to relay email to any address (unlike smtp.me.com, which will only care about the mac.com domain).
I'm a Python junior, so keep that in mind. In a Python script, I need to set a Return-Path address that is different than the sender's address. (I'm using Gmail as SMTP server.)
I've done lots of searching on this question and found plenty of "answers", but no solutions. I tried this link Setting Return-Path with Python sendmail for a MIME message but it's not working for me at all. I can change the "To:" address that the email recipient sees, but when they click "Reply", it's back to the sending email address again.
This is the function that I'm trying to write. It works well enough, except that I need to force a different Return-Path.
#!/usr/bin/python
import smtplib
import os
from email.MIMEMultipart import MIMEMultipart
from email.MIMEBase import MIMEBase
from email.MIMEText import MIMEText
from email.Utils import COMMASPACE, formatdate
from email import Encoders
import sap_mailserverdata as sf
def send_mail(sent_to, subject, body_text, sent_from_addr='', sent_from_name='', files=[], cc=[], bcc=[]):
"""Send emails with or without attachments."""
assert type(sent_to)==list
assert type(files)==list
assert type(cc)==list
assert type(bcc)==list
message = MIMEMultipart()
message['From'] = sent_from_addr
message['To'] = COMMASPACE.join(sent_to)
message['Date'] = formatdate(localtime=True)
message['Subject'] = subject
message['Cc'] = COMMASPACE.join(cc)
message.preamble = 'You need a MIME enabled mail reader to see this message.\n'
message.attach(MIMEText(body_text, 'html'))
for f in files:
part = MIMEBase('application', 'octet-stream')
part.set_payload(open(f, 'rb').read())
Encoders.encode_base64(part)
part.add_header('Content-Disposition', 'attachment; filename="%s"' % os.path.basename(f))
message.attach(part)
addresses = []
for x in sent_to:
addresses.append(x)
for x in cc:
addresses.append(x)
for x in bcc:
addresses.append(x)
mail_server = smtplib.SMTP(sf.server, sf.server_port)
mail_server.ehlo()
mail_server.set_debuglevel(1)
mail_server.starttls()
mail_server.login(sf.username, sf.password)
mail_server.sendmail(sent_from_addr, addresses, message.as_string())
mail_server.quit()
What am I missing with this function to be able to reliably specify a different replyto Return-Path?
Reply-to and return path are two distinct beasts. See the RFC.
You can set Reply-to with:
msg['reply-to'] = 'smith#acme.com'
The return-path is set by the MTA to the address that receives bounces. It is controlled by the server administrator, so unless you work for Google I don't think this is under your control.
Most of the time one is after "Reply-to"; if you really need to change the return path you must use a SMTP server under your control and google for how to do this for the specific MTA you are using - many will have a white list of users and/or hosts that can override the return path.