SendGrid Multiple Recipients Python Json - python

I am trying to write a Python script using SendGrid to send personalized emails to approx 30 people. Instead of inputting each individual's first name and email address under a substitution (as I have below), isn't there a way to link to a JSON header file (let's call it names.json) that would have all the information and that python would pull from? How and where would I reference the JSon file that would pull each person's name and email address?
import sendgrid
import os
from sendgrid.helpers.mail import Email, Content, Substitution, Mail
try:
# Python 3
import urllib.request as urllib
except ImportError:
# Python 2
import urllib2 as urllib
sg = sendgrid.SendGridAPIClient([API_KEY])
from_email = Email("sender#gmail.com")
subject = "Your Monthly Updates!"
to_email = Email("john#gmail.com")
content = Content("text/plain", " ")
mail = Mail(from_email, subject, to_email, content)
mail.personalizations[0].add_to(Email("Jane#gmail.com"))
mail.personalizations[0].add_substitution(Substitution("-name-", "John"))
mail.personalizations[0].add_substitution(Substitution("-name-", "Jane"))
mail.set_template_id(TEMPLATE_ID)
try:
response = sg.client.mail.send.post(request_body=mail.get())
except urllib.HTTPError as e:
print e.read()
exit()
print(response.status_code)
print(response.body)
print(response.headers)

Related

Using IMAP to get urls in an email not working correctly

I'm trying to find specific urls in an email, I want to be able to get every url containing a specific string. Here is my code :
import imaplib
import regex as re
def find_urls(string):
regex = r"(?i)\b((?:https?://|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}/)(?:[^\s()<>]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+(?:\(([^\s()<>]+|(\([^\s()<>]+\)))*\)|[^\s`!()\[\]{};:'\".,<>?«»“”‘’]))"
url = re.findall(regex,string)
return([x[0] for x in url])
def save_matching_urls(username, password, sender, url_string):
print("connecting to email, please wait...")
con = imaplib.IMAP4_SSL("imap.gmail.com")
con.login(username, password)
con.select('INBOX')
print("connected sucessfully, scraping email from " + sender)
(_, data) = con.search(None, '(FROM {0})'.format(sender.strip()))
ids = data[0].split()
print(str(len(ids)) +" emails found")
list_urls = []
list_good_urls = []
for mail in ids:
result, data = con.fetch(mail, '(RFC822)') # fetch the email headers and body (RFC822) for the given ID
raw_email = data[0][1]
email = raw_email.decode("utf-8").replace("\r", '').replace("\t", '').replace(" ", "").replace("\n", "")
list_url = find_urls(email)
for url in list_url:
if url_string in url:
list_good_urls.append(url)
print(str(len(list_good_urls)) + " urls found, saving...")
with open("{}_urls.txt".format(sender), mode="a", encoding="utf-8") as file:
for url in list_good_urls:
file.write(url + '\n')
print("urls saved !")
The first function is to find the urls containing the string specified. The other function connects to the mail inbox using imap and then tries to find and save matching urls from a specific sender.
To show the issue, I used the website : http://ismyemailworking.com/ that will send you an email containing two urls containing the string : "email" which are :
http://ismyemailworking.com/Block.aspx
http://ismyemailworking.com/Contact.aspx
The urls saved by the code (actually there is only one url found)
IsMyEmailWorking.com/Block.aspx=20to=20temporarily=20block==20your=20email=20address=20for=201=20hour.=20This=20solves=20the=20problem==2099%=20of=20the=20time.=20If=20after=20this=20you=20continue=20to=20have==20problems=20please=20contact=20us=20via=20the=20contact=20link=20on=20our==20website=20at=20http://IsMyEmailWorking.com/Contact.aspx
I don't know what part of the code is causing this issue, any help would be appreciated !
The variant:
from imap_tools import MailBox, A
from magic import find_urls
with MailBox('imap.mail.com').login('test#mail.com', 'pwd', 'INBOX') as mailbox:
for msg in mailbox.fetch(A(all=True)):
body = msg.text or msg.html
urls = find_urls(body)
*Regards, author of imap_tools
https://github.com/ikvk/imap_tools

SendGrid email displayed as plaintext instead of HTML

I am sending a dynamic email template through SendGrid using python. The correct HTML email template is displayed in inbox when I test the email through Sendgrid UI, but a plaintext version is displayed when the email is sent via python . Here's the code:
import sendgrid
import os
from sendgrid.helpers.mail import *
from sendgrid import SendGridAPIClient
sg = sendgrid.SendGridAPIClient('MY_KEY_HERE')
from_email = Email("example#email.com")
to_email = To("example#email.com")
subject = "Sending with SendGrid is Fun"
content = Content("text/plain", "and easy to do anywhere, even with Python")
mail = Mail(from_email, to_email, subject, content)
mail.template_id = "d-9e2812d070bb458e8d6cbd6c9b8922f6"
mail.dynamic_template_data = {
"first_name": "John",
"last_name": "Blacutt",
}
response = sg.client.mail.send.post(request_body=mail.get())
print(response.status_code)
print(response.body)
print(response.headers)
Here's the plaintext email:
If you are using a stored template and you want your dynamic content to render as HTML, you need to add an extra set of handlebars in the template itself else it will render as plain text.
EX:
<p>
{{{MailBody}}}
</p>
Notice the extra handlebars around {{MailBody}}

How to read only the 1st email body of the msg file, excluding the mails that are attached to that msg file

I am currently trying to figure out how to parse all the msg files I have stored in a specific folder and then save the body text to a dataframe but when I'm trying to extract the body of the emaill it is also extracting the emails that are attached to it. I want to extract only the body of the first email that is present in the msg file.
#src-code:https://stackoverflow.com/questions/52608069/parsing-multiple-msg-files-and-storing-the-body-text-in-a-csv-file
#reading multiple .msg files using python
from pathlib import Path
import win32com.client
outlook = win32com.client.Dispatch("Outlook.Application").GetNamespace("MAPI")
# Assuming \Documents\Email Reader is the directory containg files
for p in Path(r'C:\Users\XY\Documents\Email Reader').iterdir():
if p.is_file() and p.suffix == '.msg':
msg = outlook.OpenSharedItem(p)
print(msg.Body)
I had a similar requirement. Full code is here:
https://medium.com/#theamazingexposure/accessing-shared-mailbox-using-exchangelib-python-f020e71a96ab
For you purpose I think this snippet is going to work. It reads the first message with a specific subject line:
from exchangelib import Credentials, Account, FileAttachment
credentials = Credentials('First_Name.Last_Name#some_domain.com', 'Your_Password_Here')
account = Account('First_Name.Last_Name#some_domain.com', credentials=credentials, autodiscover=True)
filtered_items = account.inbox.filter(subject__contains='Your Search String Here')
print("Getting latest email from Given Search String...")
for item in account.inbox.filter(subject__contains='Your Search String Here').order_by('-datetime_received')[:1]:
print(item.subject, item.text_body.encode('UTF-8'), item.sender, item.datetime_received) #body of email is extracted using:: item.text_body.encode('UTF-8')
from exchangelib import Credentials, Account, FileAttachment
credentials = Credentials('First_Name.Last_Name#some_domain.com','Your_Password_Here')
account = Account('First_Name.Last_Name#some_domain.com', credentials=credentials, autodiscover=True)
unread_mails = account.inbox.filter(is_read=False)
# ur unread mail list
unread_mail_list = [mail for mail in unread_mails]
# get text body of the latest unread mail
mail_body = unread_mail_list[0].text_body

How to send pandas dataframe in table format to mail in python

I am trying to send pandas dataframe via mail. I tried but I'm not able to obtain it. My code is
code
import pandas as pd
import json
import requests
from requests.auth import HTTPBasicAuth
import datetime
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
import pdb
ticket_details=pd.DataFrame(list_values,
columns['incident',"short_description","priority","assignment_group"])
#converting a datframe into html table
df=ticket_details.to_html()
send ="xxx#xxx.com"
reciever="xxx#xxx.com"
subject="incident details "
msg = MIMEMultipart('alternative')
msg['From'] = send
msg['To'] = reciever
msg['Subject'] =subject
html_body = str(df)
messagePlain = 'Look at the incident details'
msg.attach(MIMEText(messagePlain, 'plain'))
msg.attach(MIMEText(html_body, 'html')
server = smtplib.SMTP("xxx.com")
server.sendmail(send, reciever, msg.as_string())
server.quit()
First of all please do not share personal information as mail address in your questions. Then the main problem is that you are converting your df to str and not to an html object.
# declare mixed MIME
msg = MIMEMultipart('mixed')
# convert df to html
table = df.to_html()
# attach to your mail
msg.attach(MIMEText(table, 'html')
Your HTML only contains a table and is not formatted as a full HTML page. But it reads correctly with Thunderbird. Anyway, I would add the minimum before and after the table to make it look like an acceptable HTML page:
...
prolog='''<html>
<head><title>Incident details</title></head>
<body>
'''
epilog = '</body></html>'
html_body = prolog + df + epilog
...
That is not a very nice HTML but at least, it has a html bloc, a header containing a title and a body. With that, it should be readable even on less tolerant mail readers.

Python: What is the correct MIME type for attaching html file to email

I've got a script that sends emails with html content in them.. works as expected...
I'm having trouble sending an attachment with the email.
The attachment is an html file stored in the active directory of the script... "test.html"
How do I attach the html file to the email? I've tried snippets from various other posts I've found relating to this, but each returned the same output of "no such file or directory".
code as follows:
import smtplib
import os
import email.encoders
import email.mime.text
import email.mime.base
import mimetools
import base64
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
# me == Outgoing email address
# you == Recipient's email address
me = "secret"
you = "secret"
# Create message container - the correct MIME type is multipart/alternative.
msg = MIMEMultipart('alternative')
msg['Subject'] = "TEST"
msg['From'] = me
msg['To'] = you
emailMsg = email.MIMEMultipart.MIMEMultipart('alternative')
# Create the body of the message (a plain-text and an HTML version).
html = """\
<html>
<head></head>
<body>test</p>
</body>
</html>"""
# Record the MIME types of both parts - text/plain and text/html.
part1 = MIMEText(text, 'plain')
part2 = MIMEText(html, 'html')
filename = "C:/CHRIS/ServerStatus/Oceaneering_Server_Status.html"
f = file(filename)
attachment = MIMEText(f.read(), _subtype='html')
attachment.add_header('Content-Disposition', 'attachment', filename=filename)
# 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(part1)
msg.attach(part2)
msg.attach(attachment)
# Send the message via local SMTP server.
mail = smtplib.SMTP('smtp.gmail.com', 587)
mail.ehlo()
# mail.login(username, password) to Outgoing email account
mail.login('secret', 'secret')
mail.sendmail(me, you, msg.as_string())
mail.quit()
i've updated my code in hopes to get this question back on topic... i've made a little progress with the help of Dirk and this link:
Attach a txt file in Python smtplib...
I've been able to physically send an attachment now, but the attachment is still coming through as a text type of file of sort and does not open as the original html file does.
So to reword my question... What is the corrective action for changing the MIME type of this code to correctly attach an .html file to an html based email?
The relative path and directory of my py script and the html file needed to be sent is as follows:
C:\CHRIS\ServerStatus\
This is the output i'm receiving with the code I have:
This is the way the html doc looks outside of the email script (The way it's supposed to look):
I would encourage you to use a library rather than deal with the -rather unpythonic- built-in mail modules, such as the highly recommended envelopes:
https://tomekwojcik.github.io/envelopes/index.html
install with:
pip install envelopes
Python code:
import os
from envelopes import Envelope
filename = "C:/CHRIS/ServerStatus/Oceaneering_Server_Status.html"
envelope = Envelope(
from_addr=(me),
to_addr=(you),
subject=u'Test',
text_body=u'Plain text version',
html_body=html
)
envelope.add_attachment(filename)
envelope.send('smtp.gmail.com', login='secret', password='secret', tls=True)

Categories