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}}
Related
I am sending email from Azure functions using python and sendgrid. I am able to form the other part of the email but when I am trying to insert logo in signature of the email is not displaying that. Rest HTML is rendering fine.(till href)
Following is my code :
import sendgrid
from sendgrid import SendGridAPIClient
from sendgrid.helpers.mail import Mail
message = Mail(
from_email=email_from,
to_emails=email_to,
subject=email_subject,
html_content= '<br>Hi '+name+ ','+
'<br>body of the email. Working fine.' +
'<br><a href='+no+'>No'</a>\n' +
'<br><br>LOGO--><img src="doc.png" alt="W3Schools.com"/>'+
'</html>'
)
response = sg.send(message)
print(response.status_code)
I tried pointing out URL in src too and it did not help.
There are 3 options to achieve this:
CID Embedded Images (Inline Images)
Inline Embedding (Base64 Encoding)
Linked Images
Check out below links for implementation details:
https://sendgrid.com/blog/embedding-images-emails-facts/
https://github.com/sendgrid/sendgrid-python/issues/736
I am trying to send email using sendgrid using python django. For some reason, the email is being delivered but without the html content in it. What could I be doing wrong ?
def sendemail(sender,recipient,subject,content,url):
sg = sendgrid.SendGridAPIClient(apikey="")
from_email = Email(sender)
to_email = Email(recipient)
subject = subject
objects = {
"message":content,
"domain":url
}
html_content = get_template('sendemail.html').render(objects)
print ('htmlcontent',html_content)
content = Content("text/html",html_content)
mail = Mail(from_email, subject, to_email, content)
response = sg.client.mail.send.post(request_body=mail.get())
print(response.status_code)
print(response.body)
print(response.headers)
I think that you have to set text/plain content as well.
You can try something like this :
mail = Mail(from_email, subject, to_email)
mail.add_content(Content("text/plain", "plain message"))
mail.add_content(Content("text/html", html_content ))
I want to send HTML webpage as a mail body using Python and Flask. I tried using MIME module, but somehow I am not being able to send mail. If anyone has any expertise on this, can you please help me.
It would be great if you could provide some code as well.
flask-mail is a good tool that I use to render the template to render HTML as the body of my mail.
from flask_mail import Message
from flask import render_template
MAIL_USERNAME = os.environ.get('MAIL_USERNAME')
MAIL_PASSWORD = os.environ.get('MAIL_PASSWORD')
def send_mail_flask(to,subject,template,**kwargs):
msg = Message(subject=subject,sender='email#ofTheSender.com', recipients=to)
msg.body = render_template('template.txt', **kwargs)
msg.html = render_template('template.html', **kwargs)
mail.send(msg)
The template is the HTML file you wish to include in your mail and you can also add a text version using msg.body!
You may need to add more environment variables according to the SMTP service you use.
I recently made a pretty awesome email library and I decided to make a Flask extension for it as well: Flask-Redmail
Install
pip install flask-redmail
Configuration
from flask import Flask
from flask_redmail import RedMail
app = Flask(__name__)
email = RedMail(app)
# Setting configs
app.config["EMAIL_HOST"] = "localhost"
app.config["EMAIL_PORT"] = 0
app.config["EMAIL_USERNAME"] = "me#example.com"
app.config["EMAIL_PASSWORD"] = "<PASSWORD>"
app.config["EMAIL_SENDER"] = "no-reply#example.com"
Simple Example
You may send emails simply:
#app.route("/send-email")
def send_email():
email.send(
subject="Example email",
receivers=["you#example.com"],
html="""
<h1>Hi,</h1>
<p>this is an example.</p>
"""
)
Template Example
It can also use your default Jinja env. Create a file emails/verify.html to your Flask template folder that looks like this:
<h1>Hi, you visited {{ request.endpoint }}.</h1>
Then use this template:
#app.route("/send-email-template")
def send_email():
email.send(
subject="Template example",
receivers=["you#example.com"],
html_template="emails/verify.html"
)
Flask Redmail is quite a simple wrapper for Red Mail and Red Mail is pretty extensive. It can:
Send attachments from various types
Embed images and plots to the HTML
Embed prettified tables to the HTML
Supports Jinja out-of-the-box
Gmail and Outlook are preconfigured
I hope you find it useful.
Links:
Documentation
Source Code
Releases
Red Mail:
Documentation
Source Code
Releases
Try using FlaskMail https://pythonhosted.org/flask-mail/
msg = Message(
recipients=[''],
sender='xx#zz.yy',
reply_to='aa#bb.cc',
subject=mail.subject
)
msg.html = mail.body
mail.send(msg)
here, mail is an imported file from "mails" directory,
and body is an HTML markup.
On a separate python file (emails.py) I created an email class that contains all the emails (as class methods) to be sent to the user based on his actions as below:
class Email:
def accountCreation():
body = "<html> <body> <p> {} </p> <br> <br> <p> Lorem Ipsum is simply dummy text of the printing and typesetting industry.</p> </body> </html>"
return body
then on another file (app.py) where I made use of flask_mail library I have:
from flask_mail import Mail, Message
import emails
mailer = emails.Email()
try:
email = "johndoe#mail.com"
body = mailer.accountCreation()
msg = Message('Hello',recipients=[email])
msg.html = body
mail.send(msg)
except Exception as e:
print(e)
Firstly, ensure there's a folder in your apps directory called templates. This is where all your html templates should be.
**server.py**
from flask-mail import Mail, Message
from flask import Flask
import os
app = Flask(__name__)
send_mail = Mail(app)
context={
"fullname": fullname,
"otp_code": otp_code,
"year": datetime.now().year,
"subject":"Registration Mail",
}
email_message = Message(
subject=mail_subject,
sender=os.getenv("ADMIN_EMAIL"),
recipients=[receipients_email],
html=render_template(template_name_or_list="otp.html", **context)
)
send_mail.send(email_message)
where "otp.html" is an existing html template in your templates folder
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)
I setup a system Django/Celery/Redis. And I used EmailMultiAlternatives to send my HTML and Text email.
When I send email as part of the request process, the email is sent in HTML. All runs well and it wraps around a function. Here's the code:
def send_email(email, email_context={}, subject_template='', body_text_template='',
body_html_template='', from_email=settings.DEFAULT_FROM_EMAIL):
# render content
subject = render_to_string([subject_template], context).replace('\n', ' ')
body_text = render_to_string([body_text_template], context)
body_html = render_to_string([body_html_template], context)
# send email
email = EmailMultiAlternatives(subject, body_text, from_email, [email])
email.attach_alternative(body_html, 'text/html')
email.send()
However, when I tried to run it as a Celery Task, like below, it just sent as "text/plain". What could be the problem? Or what can I do to find out more? Any hint or solution are greatly appreciated.
#task(name='tasks.email_features', ignore_result=True)
def email_features(user):
email.send_email(user.email,
email_context={'user': user},
subject_template='emails/features_subject.txt',
body_text_template='emails/features_body.txt',
body_html_template='emails/features_body.html')
Celery does not affect the executing results of tasks. Have you restarted celeryd after make change to the task? It's important for celery to reload the Python code.
When you were using EmailMultiAlternatives and email.attach_alternative(body_html, 'text/html'), the email was sent in the Content-Type: multipart/alternative; and the text/html is an alternative one, it depends on mail receipts to choose the content type of the mail during the rendering. So is the receipt same one between the view procedure and celery procedure?
You could output the sending mail directly, through python -m smtpd -n -c DebuggingServer localhost:25 to find out the actual messages. I've tested on my mac w/ redis-backed Celery, the outputs of the examples taken from the official doc are same as expected.
from django.core import mail
from django.template.loader import render_to_string
from django.utils.html import strip_tags
class SendEmail(Task):
name="send_email"
def run(self,email):
subject = 'Daily News Letter'
html_message = render_to_string('letter.html', {'context': 'values'})
plain_message = strip_tags(html_message)
from_email = env('EMAIL_HOST_USER')
mail.send_mail(subject, plain_message, from_email, [email], html_message=html_message)
return None
send_email = celery_app.register_task(SendEmail())