Im triying to send a mass email with django's "send_mass_email" method, i've read the documentation but the examples only show plain text messages.
How can i be able to send HTML messages with the "send_mass_emal" method? i tried like a regular email but the recived only html code. Here is my code:
for row_index in range(12, sheet.nrows):
if sheet.cell(rowx=row_index, colx=0).value != "":
template = get_template("MonthlyEmail.html")
context = Context({
'name': str(clean_string(sheet.cell(rowx=row_index, colx=2).value)),
'doc_type': str(sheet.cell(rowx=row_index, colx=4).value),
'document': str(sheet.cell(rowx=row_index, colx=3).value),
'email': str(sheet.cell(rowx=row_index, colx=5).value),
'acc_numb': str(sheet.cell(rowx=row_index, colx=6).value),
'brute_salary': str(sheet.cell(rowx=row_index, colx=8).value),
'vacation_commision': str(sheet.cell(rowx=row_index, colx=9).value),
'brute_total': str(sheet.cell(rowx=row_index, colx=10).value),
'social_sec': str(sheet.cell(rowx=row_index, colx=14).value),
'isr': str(sheet.cell(rowx=row_index, colx=27).value),
'other_retention': str(sheet.cell(rowx=row_index, colx=13).value),
'net_payment': str(sheet.cell(rowx=row_index, colx=29).value)
})
content = template.render(context)
messages.append(('Monthly Salary Report', content,
'intranet#intranet.com',
[str(sheet.cell(rowx=row_index, colx=5).value)]))
send_mass_mail_html(messages, fail_silently=False)
It does not look like send_mass_email() supports HTML emails. But there is a way to do it by taking inspiration from the code of Django's send_mail() function:
connection = connection or get_connection(
username=auth_user,
password=auth_password,
fail_silently=fail_silently,
)
mail = EmailMultiAlternatives(subject, message, from_email, recipient_list, connection=connection)
if html_message:
mail.attach_alternative(html_message, 'text/html')
mail.send()
The general strategy seems to create a connection first, then for each email you need to send, create an instance of EmailMultiAlternatives, passing it the existing connection, then send it, exactly as send_mail but in a loop...
I have wrote my own functionality to use mass email by using the django documentaion as reference.
from django.conf import settings
from django.core.mail import EmailMultiAlternatives
from django.template.loader import render_to_string
def get_rendered_html(template_name, context={}):
html_content = render_to_string(template_name, context)
return html_content
def send_email(subject, html_content, text_content=None, from_email=None, recipients=[], attachments=[], bcc=[], cc=[]):
# send email to user with attachment
if not from_email:
from_email = settings.DEFAULT_FROM_EMAIL
if not text_content:
text_content = ''
email = EmailMultiAlternatives(
subject, text_content, from_email, recipients, bcc=bcc, cc=cc
)
email.attach_alternative(html_content, "text/html")
for attachment in attachments:
# Example: email.attach('design.png', img_data, 'image/png')
email.attach(*attachment)
email.send()
def send_mass_mail(data_list):
for data in data_list:
template = data.pop('template')
context = data.pop('context')
html_content = get_rendered_html(template, context)
data.update({'html_content': html_content})
send_email(**data)
message1 = {
'subject': 'Subject here',
'text_content': 'Here is the message',
'from_email': 'from#example.com',
'recipients': ['first#example.com', 'other#example.com'],
'template': "template1.html",
'context': {"d1": "mydata"}
}
message2 = {
'subject': 'Subject here',
'text_content': 'Here is the message',
'from_email': 'from#example.com',
'recipients': ['first#example.com', 'other#example.com'],
'template': "template2.html",
'context': {"d2": "mydata"}
}
send_mass_mail([message1, message2])
Reference: https://docs.djangoproject.com/en/1.11/_modules/django/core/mail/#send_mass_mail
I wrote custom mass mail method and it is working fine:-
from django.core.mail.message import EmailMessage
from django.core.mail import get_connection
def send_custom_mass_mail(datatuple, fail_silently=False, auth_user=None,
auth_password=None, connection=None):
"""
coloned fromt he core
"""
connection = connection or get_connection(
username=auth_user,
password=auth_password,
fail_silently=fail_silently,
)
EmailMessage.content_subtype = 'html'
messages = [
EmailMessage(subject, message, sender, recipient, connection=connection)
for subject, message, sender, recipient in datatuple
]
return connection.send_messages(messages)
Then I use as per document:
send_custom_mass_mail((mail_to_lead), fail_silently=False)
Related
Tests fail with an error response meaning that it is likely to be allowing email with wrong data and yet it should throw an HttpResponse as expected, I have tried to figure it out why my test is failing and returning 200 http status code but not as expected = 400.
reset password
class ResetPassword(View):
form_class = ForgetPasswordForm()
template_name = 'authentication/password_reset.html'
def get(self, request):
form = self.form_class
return render(request, self.template_name, {'form': form})
def post(self, request):
msg = None
form = ForgetPasswordForm(request.POST)
if form.is_valid():
data = form.cleaned_data.get('email')
associated_users = Users.objects.filter(Q(email = data))
if associated_users.exists():
for user in associated_users:
subject = 'Password Reset Requested'
email_template_name = "authentication/password_reset_email.txt"
c = {
"email": user.email,
'domain': '127.0.0.1:8000',
'site_name': 'ATB Project Organizer',
'uid': urlsafe_base64_encode(force_bytes(user.pk)),
'user': user,
'token': default_token_generator.make_token(user),
'protocol': 'http',
}
email = render_to_string(email_template_name, c)
try:
send_mail(subject, email, 'admin#example.com', [user.email], fail_silently=False)
except BadHeaderError:
return HttpResponse('Invalid header found')
msg = 'You have successfully reset your password!'
return redirect('/password_reset/done/')
else:
msg = 'No records found for this email, please make sure you have entered the correct email address!'
form = ForgetPasswordForm()
return render(request, 'authentication/password_reset.html', {'form': form, 'msg': msg})
Test to raise an exception
from django.test import TestCase
from django.urls import reverse
from django.core import mail
from django.contrib.auth import get_user_model
User = get_user_model()
class PasswordResetTest(TestCase):
def setUp(self):
self.user1 = User.objects.create_user("user1", email = "user1#mail.com", password = "password#121", orcid = '1234567890987654')
self.user2 = User.objects.create_user("user2", email = "user2#mail.com", password = "password#122", orcid = '1234567890987655')
self.user3 = User.objects.create_user("user3#mail.com", email = "not-that-mail#mail.com", password = "password#123", orcid = '1234567890987656')
self.user4 = User.objects.create_user("user4", email = "user4#mail.com", password = "passs", orcid = '1234567890987657')
self.user5 = User.objects.create_user("user5", email = "uѕer5#mail.com", password = "password#125", orcid = '1234567890987658') # email contains kyrillic s
self.user={
'username':'username',
'email':'testemail#gmail.com',
'password1':'password#123',
'password2':'password#123',
'orcid': '1234123412341239',
}
def test_user_can_resetpassword(self):
response = self.client.get(reverse('resetpassword'))
self.assertEqual(response.status_code, 200)
self.assertTemplateUsed(response, 'authentication/password_reset.html')
# Then test that the user doesn't have an "email address" and so is not registered
response = self.client.post(reverse('resetpassword'), {'email': 'admin#example.com'}, follow=True)
self.assertEqual(response.status_code, 200)
# Then test that the user doesn't have an "email address" and so is not registered
# Then post the response with our "email address"
# Then post the response with our "email address"
response = self.client.post(reverse('resetpassword'),{'email':'user1#mail.com'})
self.assertEqual(response.status_code, 302)
# At this point the system will "send" us an email. We can "check" it thusly:
self.assertEqual(len(mail.outbox), 1)
self.assertEqual(mail.outbox[0].subject, 'Password Reset Requested')
def test_exception_raised(self):
# verify the email with wrong data
data = {"uid": "wrong-uid", "token": "wrong-token"}
response = self.client.post(reverse('resetpassword'), data, format='text/html')
self.assertEqual(response.status_code, 400)
Error
File "../tests/test_passwordreset.py", line 55, in test_exception_raised
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
AssertionError: 200 != 400
Failing code
The default HTTP status code when you instantiate the HttpResponse class is 200 (OK). This is why your test fails.
Try this:
...
except BadHeaderError:
return HttpResponse('Invalid header found', status=400)
# Or more verbose:
# return HttpResponse('Invalid header found', status=HttpStatus.BAD_REQUEST)
...
or
...
except BadHeaderError:
return HttpResponseBadRequest('Invalid header found')
...
See the docs for more details.
I am trying to send two different emails using the django send_mass_mail function. I'm very new to django, and I'm struggling to get it to work. The send-Mail function works fine when I use it, but I want to send different emails to the customer and the site owner when a purchase is made. Any help with this would be amazing! Thanks so much!
def _send_confirmation_email(self, order):
""" Send the user a confirmation email """
cust_email = order.email
subject = render_to_string(
'checkout/confirmation_emails/confirmation_email_subject.txt',
{'order': order})
body = render_to_string(
'checkout/confirmation_emails/confirmation_email_body.txt',
{'order': order, 'contact_email': settings.DEFAULT_FROM_EMAIL})
subject2 = render_to_string('Order Placed', {'order':order})
body2 = render_to_string(
'An order has been placed',
{'order': order}
)
message1 = (
subject,
body,
settings.DEFAULT_FROM_EMAIL,
[cust_email]
)
message2 = (
subject2,
body2,
settings.DEFAULT_FROM_EMAIL,
['test#hotmail.com']
)
send_mass_mail((message1, message2), fail_silently=False)
Anyone know how to solved my issue, Im working with DJango-email with multiple recipient. Sending email in multiple recipient accounts from my DB are working, but now I want to send email and the email:body are depending on the Data ID.
This are the email list,
Scenario: Plate_No: 123123 will be send to example_email1#gmail.com only and ABV112 will be send again to example_email2#gmail.com and so on. Only the Plate_no assign in email will send, can someone help me to work my problem. Thank you!
auto send email script:
class HomeView(ListView):
cstatus = VR.objects.filter(Deadline__date = datetime.datetime.today(), sent_email="No")
print(cstatus)
recipient_list = []
for recipient in cstatus:
recipient_list.append(recipient.email)
print(recipient_list)
plate = ""
for carreg in cstatus:
print(carreg.plate_no)
plate = carreg.plate_no
if plate != "":
subject = 'FMS Automated Email'
html_message = render_to_string('vr/pms_email.html', {'content':cstatus})
plain_message = strip_tags(html_message)
from_email = 'FMS <fms#gmail.com>'
mail.send_mail(subject, plain_message, from_email, recipient_list, html_message=html_message, fail_silently=False)
cstatus.update(sent_email="Yes")
model = VR
context_object_name = 'list'
template_name = 'vr/list.html'
You can use a for-loop on your cstatus queryset to send the emails to the recipents. Did not test it, but it should look something like this:
for item in cstatus:
subject = 'FMS Automated Email'
html_message = render_to_string('vr/pms_email.html'{'content':item.Plate_no})
plain_message = item.Plate_no
recipent_list = [item.email]
from_email = 'FMS <fms#gmail.com>'
mail.send_mail(subject, plain_message, from_email, recipient_list, html_message=html_message, fail_silently=False)
item.update(sent_email="Yes")
According to what I understood regarding your query, this might what you need:
class HomeView(ListView):
cstatus = VR.objects.filter(Deadline__date = datetime.datetime.today(), sent_email="No")
print(cstatus)
recipient_list = {}
for recipient in cstatus:
recipient_list[recipient.plate_no] = recipient.email
print(recipient_list)
for carreg in cstatus:
print(carreg.plate_no)
plate = carreg.plate_no
if plate != "":
subject = 'FMS Automated Email'
html_message = render_to_string('vr/pms_email.html', {'content':carreg}) # or use plate for just plate_no
plain_message = strip_tags(html_message)
from_email = 'FMS <fms#gmail.com>'
mail.send_mail(subject, plain_message, from_email, [recipient_list[plate]], html_message=html_message, fail_silently=False)
cstatus.update(sent_email="Yes")
model = VR
context_object_name = 'list'
template_name = 'vr/list.html'
Or Use mass emailing in django:
link: https://docs.djangoproject.com/en/1.8/topics/email/#send-mass-mail
message1 = ('Subject here', 'Here is the message', 'from#example.com', ['first#example.com', 'other#example.com'])
message2 = ('Another Subject', 'Here is another message', 'from#example.com', ['second#test.com'])
send_mass_mail((message1, message2), fail_silently=False)
Add all the above message results in a tuple and add it in send_mass_mail. For eg.
datatuple = (
(subject, plain_message, from_email, to_email),
(subject, plain_message, from_email, to_email)
) # to_mail -> recipient_list[plate]
send_mass_mail(datatuple)
Let me know if I was wrong.
From the below code, I am sending mail with some info.Here i need to get the message to my mail id,When he/she opens the mail.
How to do this in Python.
def Data(request):
templateName = "sendmail.html"
mapDictionary = {'fromMail': "xxxx.xxxx#gmail.com", 'password': "xxxxx", 'toMail': "yyyyy.yyyy#gmail.com#gmail.com",
"subject": "New Trip Confirmation", 'username': 'Ramesh','trip_start_date' : '2014-02-10',
'trip_start_place' : 'Visak', 'trip_start_time' : '11:00 AM', "templateName" : templateName
}
print ("call send mail from processNewTripData...")
return sendmail(request, mapDictionary)
def sendmail(request, mapDictionary):
try:
server = smtplib.SMTP('smtp.gmail.com',587)
server.starttls()
server.login(mapDictionary["fromMail"],mapDictionary["password"])
context = Context(mapDictionary)
html_content = render_to_string(mapDictionary["templateName"], context)
#text_content = "This is Confirmation mail"
msg = MIMEText(html_content,'html')
msg['Subject'] = mapDictionary["subject"]
server.sendmail(mapDictionary["fromMail"], mapDictionary['toMail'], msg.as_string())
to_json = {'result' : "True"}
return HttpResponse(simplejson.dumps(to_json), content_type='application/json')
except Exception as e:
print str(e)
to_json = {'result' : "False"}
return HttpResponse(simplejson.dumps(to_json), content_type='application/json')
Have a try and add this header:
Disposition-Notification-To: "User" <user#user.com>
The reader may need to confirm that you get a reply. Also adding html content served by your server can be an option to recognize that the mail is read.
You should be able to do this with any of these lines
msg['Disposition-Notification-To'] = '"User" <user#user.com>'
msg['Disposition-Notification-To'] = 'user#user.com'
I wrote a simple contact form for a client in Django. However, whenever it sends e-mail, it wraps the header values in u'' objects. For example, the From: header is
From: (u'my#email.com',)
Here's the code that sends the message:
The form:
class ContactForm(forms.Form):
name = forms.CharField(max_length=100)
sender = forms.EmailField()
subject = forms.CharField(max_length=255)
message = forms.CharField(widget=forms.widgets.Textarea(attrs={'rows':15, 'cols': 72}))
The contact function:
def contact(request):
RECAPTCHA_PRIVATE_KEY = '******************'
captcha_error = ''
if request.method == 'POST':
form = ContactForm(request.POST)
captcha_response = captcha.submit(request.POST.get("recaptcha_challenge_field", None),
request.POST.get("recaptcha_response_field", None),
RECAPTCHA_PRIVATE_KEY,
request.META.get("REMOTE_ADDR", None))
if not captcha_response.is_valid:
captcha_error = "&error=%s" % captcha_response.error_code
elif form.is_valid():
name = form.cleaned_data['name'],
sender = form.cleaned_data['sender'],
subject = form.cleaned_data['subject'],
message = form.cleaned_data['message']
recipients = ['email#email.com']
try:
send_mail(subject, message, sender, recipients)
except BadHeaderError:
pass
flash_message = 'Thank you for contacting us. We will get back to you shortly.'
return render_to_response('pages/contact.html', {
'form': form,
'captcha_error': captcha_error,
'message': flash_message
})
It sends the e-mail perfectly, I check the appropriate mailbox and the e-mail appears. But these u'' objects prevent the e-mail's subject from appearing correctly and prevents it from being replied to.
What am I doing wrong?
Thanks in advance.
Lose the trailing commas here:
elif form.is_valid():
name = form.cleaned_data['name']
sender = form.cleaned_data['sender']
subject = form.cleaned_data['subject']
message = form.cleaned_data['message']