My Django app sends an email as follows:
mail_subject='Hi'
to_email='xyz#gmail.com'
message=render_to_string('app1/xyz.html',{
'user':User1,'var1':'BLUE'})
email = EmailMessage(mail_subject, message, to=[to_email])
email.send();
xyz.html looks like below:
I would like for the following string to be bold
<strong>{{var1}}</strong>
but it just shows as <strong>BLUE</strong> in the email. I would like to see BLUE
from django.core.mail import send_mail
from django.template.loader import render_to_string
msg_html = render_to_string('templates/xyz.html', {'some_params': some_params})
send_mail(
'email title',
'Hi',
'sender#gmail.com',
['xyz#gmail.com'],
html_message=msg_html,
)
We can create any structure (bold/italic) in xyz.html and it will display nicely inside an email.
Related
I'm trying to add change password functionality to a Django / React app. I'm using django-rest-passwordreset library for creating Reset or Forgot Password API using Django Rest Framework.
After I type the email that registered, I've managed get the token from the console
But I'm struggling to find a way to send an email to their email address with the link to reset their password along the given token. I've tried the SMTP Method or SendGrid. Was trying this way and this way
Can someone show me the correct way to make this work? Thanks a lot.
Edit :
Settings.py
INSTALLED_APPS = [
...
'rest_framework',
'django_rest_passwordreset',
]
Urls.py
from django.urls import path, include
urlpatterns = [
...
path('api/password_reset/', include('django_rest_passwordreset.urls', namespace='password_reset')),
]
Models.py
from django.dispatch import receiver
from django.urls import reverse
from django_rest_passwordreset.signals import reset_password_token_created
from django.core.mail import send_mail
#receiver(reset_password_token_created)
def password_reset_token_created(sender, instance, reset_password_token, *args, **kwargs):
email_plaintext_message = "{}?token={}".format(reverse('password_reset:reset-password-request'), reset_password_token.key)
send_mail(
# title:
"Password Reset for {title}".format(title="Astect"),
# message:
email_plaintext_message,
# from:
"astect#asei.co.id",
# to:
[reset_password_token.user.email]
)
You can make like this
#receiver(reset_password_token_created)
def password_reset_token_created(sender, instance, reset_password_token, *args, **kwargs):
# send an e-mail to the user
context = {
"current_user": reset_password_token.user,
"username": reset_password_token.user.username,
"email": reset_password_token.user.email,
"reset_password_url": "{}?token={}".format(
instance.request.build_absolute_uri(reverse("password_reset:reset-password-confirm")),
reset_password_token.key,
),
}
# render email text
email_html_message = render_to_string("email/user_reset_password.html", context)
email_plaintext_message = render_to_string("email/user_reset_password.txt", context)
msg = EmailMultiAlternatives(
# title:
"Password Reset for {title}".format(title="Pinper"),
# message:
email_plaintext_message,
# from:
"<youremail>",
# to:
[reset_password_token.user.email],
)
msg.attach_alternative(email_html_message, "text/html")
msg.send()
And create a template like this
....
....
<body>
<h1>Reset password for {{current_user}}</h1>
<h4>You write your message</h4>
{{ reset_password_url }}
</body>
The template receive a context with some variables: current_user, username, email, reset_password_url .
There is a feedback form in which the user can write a text message and attach the file.
This form is sent to managers by mail (gmail, for example).
Is there any way to make this file come to mail in its normal form (in a preview, for example) so that you can immediately see or download it?
For now, I'm just sending a file link in the message.
Thanks for help #dirkgroten
def send_contact_us_notification(file, name: str, email: str, body: str, phone='', nda=False):
try:
file = settings.MEDIA_URL[1:] + str(contact_form.file)
from django.core.mail import EmailMessage
msg = EmailMessage('Subject of the Email', 'Body of the email', 'dinamo.mutu111#gmailcom', ['dimaonlyvit#gmail.com'])
msg.attach_file(file)
msg.send()
except Exception as e:
print(e)
I'm new in Django ! I don't know how to send email in Django. I refer Django documentation but it didn't help me . I need to send email with html page to different users .In models.py i have two values Name and Email. When i click button ,the html page should be send to appropriate user's Email
There are a lot of different solutions how to send emails in django.
You can use even php, or any scripting language if you feel it's complicated to use only python/django code.
Just an example of email utility from custom email subscription:
email_utility.py:
import logging, traceback
from django.urls import reverse
import requests
from django.template.loader import get_template
from django.utils.html import strip_tags
from django.conf import settings
def send_email(data):
try:
url = "https://api.mailgun.net/v3/<domain-name>/messages"
status = requests.post(
url,
auth=("api", settings.MAILGUN_API_KEY),
data={"from": "YOUR NAME <admin#domain-name>",
"to": [data["email"]],
"subject": data["subject"],
"text": data["plain_text"],
"html": data["html_text"]}
)
logging.getLogger("info").info("Mail sent to " + data["email"] + ". status: " + str(status))
return status
except Exception as e:
logging.getLogger("error").error(traceback.format_exc())
return False
Don't forget to create a token which we will verify when user clicks the confirmation link. Token will be encrypted so that no one can tamper the data.
token = encrypt(email + constants.SEPARATOR + str(time.time()))
Also check this link and this.
Here is a naive exemple to leverage django send_mail:
import smtplib
from django.core.mail import send_mail
from django.utils.html import strip_tags
from django.template.loader import render_to_string
#user will be a queryset like:
users = User.objects.all() # or more specific query
subject = 'Subject'
from_email = 'from#xxx.com'
def send_email_to_users(users,subject,from_email):
full_traceback = []
for user in users:
to = [user.email] # list of people you want to sent mail to.
html_content = render_to_string('mail_template.html', {'title':'My Awesome email title', 'content' : 'Some email content', 'username':user.username}) # render with dynamic context you can retrieve in the html file
traceback = {}
try:
send_mail(subject,strip_tags(html_content),from_email, to, html_message=html_content, fail_silently=False)
traceback['status'] = True
except smtplib.SMTPException as e:
traceback['error'] = '%s (%s)' % (e.message, type(e))
traceback['status'] = False
full_traceback.append(traceback)
errors_to_return = []
error_not_found = []
for email in full_traceback:
if email['status']:
error_not_found.append(True)
else:
error_not_found.append(False)
errors_to_return.append(email['error'])
if False in error_not_found:
error_not_found = False
else:
error_not_found = True
return (error_not_found, errors_to_return)
#really naive view using the function on top
def my_email_view(request,user_id):
user = get_object_or_404(User, pk=user_id)
subject = 'Subject'
from_email = 'myemail#xxx.com'
email_sent, traceback = send_email_to_users(user, subject, from_email)
if email_sent:
return render(request,'sucess_template.html')
return render(request,'fail_template.html',{'email_errors' : traceback})
In your template mail_template.html:
<h1>{{title}}</h1>
<p>Dear {{username}},</p>
<p>{{content}}</p>
And don't forget to set the email settings in settings.py: https://docs.djangoproject.com/fr/2.2/ref/settings/#email-backend
Send_mail from docs :https://docs.djangoproject.com/fr/2.2/topics/email/#send-mail
Render_to_string from the doc: https://docs.djangoproject.com/fr/2.2/topics/templates/#django.template.loader.render_to_string
I want to sends an email but sent mail is empty.
how to send an email, and then put a copy of it in the "Sent" mail folder.
what can i do?
Yes, its possible.
Basicaly you need to create an MIME email and then send it throug smptlib and than save it on Sent with imaplib.
The official imaplib documentation.
More detailed examples of using imaplib.
Here is an example:
import time
import ssl
import imaplib
import smtplib
import email
from email import encoders
from email.mime.base import MIMEBase
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
class Mail:
def __init__(self):
# considering the same user and pass for smtp an imap
self.mail_user = 'youruser#yourdomain.com'
self.mail_pass = 'pass'
self.mail_host = 'mail.yourdomain'
def send_email(self, to, subject, body, path, attach):
message = MIMEMultipart()
message["From"] = self.mail_user
message["To"] = to
message["Subject"] = subject
message.attach(MIMEText(body, "plain"))
with open(path + attach, "rb") as attachment:
part = MIMEBase("application", "octet-stream")
part.set_payload(attachment.read())
encoders.encode_base64(part)
part.add_header(
"Content-Disposition",
"attachment; filename= \"" + attach + "\"",
)
message.attach(part)
text = message.as_string()
context = ssl.create_default_context()
with smtplib.SMTP_SSL(self.mail_host, 465, context=context) as server:
result = server.login(self.mail_user, self.mail_pass)
server.sendmail(self.mail_user, to, text)
imap = imaplib.IMAP4_SSL(self.mail_host, 993)
imap.login(self.mail_user, self.mail_pass)
imap.append('INBOX.Sent', '\\Seen', imaplib.Time2Internaldate(time.time()), text.encode('utf8'))
imap.logout()
if __name__ == '__main__':
m = Mail()
m.send_email('someone#somewhere.com', 'Hello', 'Its just a test!', 'c:\\', 'test.pdf')
I've spent a lot of time figuring out how to send email at a specified time in Django, so I am posting it with answer here to save others some time.
My use case is sending email during working hours. Using celery for that is a bad idea. But Sendgrid can send emails with a delay of up to 3 days. That's what we need.
That what I made:
from django.core.mail import EmailMultiAlternatives
from django.template.context import Context
from django.template.loader import get_template
from smtpapi import SMTPAPIHeader
def send_email(subject, template_name, context, to, bcc=None, from_email=settings.DEFAULT_FROM_EMAIL, send_at=None):
header = SMTPAPIHeader()
body = get_template(template_name).render(Context(context))
if send_at:
send_at = {"send_at": send_at}
header.set_send_at(send_at)
email = EmailMultiAlternatives(
subject=subject,
body=body,
from_email=from_email,
to=to,
bcc=bcc,
headers={'X-SMTPAPI': header.json_string()}
)
email.attach_alternative(body, 'text/html')
email.send()
Don't forget to set it in header X-SMTPAPI cause I couldn't find it anywhere..
And send_at should be a timestamp
Also here you could see how to add headers or anything but with sendgrid.SendGridClient:
https://sendgrid.com/docs/Utilities/code_workshop.html/scheduling_parameters.html
import sendgrid
...
sg = sendgrid.SendGridClient('apiKey')
message = sendgrid.Mail()
message.add_to('John Doe <example#mailinator.com>')
message.set_subject('Example')
message.set_html('Body')
message.set_text('Body')
message.set_from('Doe John <example#example.com>')
message.smtpapi.set_send_at(timestamp)
sg.send(message)
send_at = {"send_at": send_at} produces X-SMTPAPI: {"send_at": {"send_at": 1643934600}} when you print the headers.
Instead, just use send_at = send_at or you can as well delete the line entirely.