I have a functionality in a Django app to send an email to all the registered users, I'm currently doing it with 'EmailMessage' and it works perfectly but everybody gets to see every other recipient's email which is unwanted.
Is there a way to hide recipients using the Django mailing functions?
Thank you.
when you instantiate EmailMessage class you can provide bcc attribute such as the example.
Here is the EmailMessage class
class EmailMessage(object):
"""
A container for email information.
"""
content_subtype = 'plain'
mixed_subtype = 'mixed'
encoding = None # None => use settings default
def __init__(self, subject='', body='', from_email=None, to=None, bcc=None,
connection=None, attachments=None, headers=None, cc=None):
so if you provide bcc recipient with the attribute name. you can set the target email as bcc recipient.
message = EmailMessage('hello', 'body', bcc=['user#email.com',])
message.send()
http://en.wikipedia.org/wiki/Blind_carbon_copy
https://docs.djangoproject.com/en/1.7/topics/email/
Definitely BCC each address, this should hide them for any recipient. By the looks of the docs you will need to create your own EmailMessage rather than using the predefined wrappers.
You can try this code format if you want to send Mass Email using send_mass_mail() function.
from django.core.mail import send_mass_mail
subject = 'test subject'
message = 'test message'
from_email = 'from#from.com'
recipient_list = ['a#a.com', 'b#b.com', 'c#c.com']
messages = [(subject, message, from_email, [recipient]) for recipient in recipient_list]
send_mass_mail(messages)
Related
Using send_mass_mail will result in all the emails being shown in the 'To' field.
I came across this solution but it hides all user Emails. And it looks weird in the inbox because the 'To' field is empty.
What I want is to use send_mass_mail showing only the receiving recipient's Email in the 'To' field. E.g. If I send Emails to jack#gmail.com and jane#gmail.com, jack should see jack#gmail.com and jane should see jane#gmail.com in the 'To' field.
Is there a way to achieve this? Or do I have to use loop over each recipient with send_mail?
You can send separate emails directly to different recipients using send_mass_mail, you just need to get the arguments structured properly:
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)
This is not too different from iterating over the recipients yourself and sending each email separately, except for one key difference; using send_mass_email will result in all emails being sent via a single connection to your mail server. Doing it iteratively in your code will result in connections being opened and closed for each email and as a result will be slower due to that overhead.
Try This:
from django.core.mail import send_mass_mail
subject = 'test subject'
message = 'test message'
from_email = 'from#from.com'
recipient_list = ['a#a.com', 'b#b.com', 'c#c.com']
messages = [(subject, message, from_email, [recipient]) for recipient in recipient_list]
send_mass_mail(messages)
I have a contact form in my template, so that when a user requests information about a house users can contact different sellers to request information. I don't know how I can send email to different accounts as you know in the system exist multiple sellers.
This is my contact form :
Where "Nombre" is the name of the user that wants information and "Mail" is the e-mail of the user that wants information.
The seller of the House is who will receive the email.
I can't use that:
EMAIL_HOST_USER =
EMAIL_HOST_PASSWORD =
because not only one person will receive all emails
You can use EmailMultiAlternatives and customize your to list
you can try:
from django.core.mail import EmailMultiAlternatives
def view_where_i_send_email(request):
# some view content
# vars to render into html email template
d = Context({'arg_1': arg_1, 'arg_n' : arg_n,})
# get the template to tge email
template = "emailtemplate.html"
htmly = get_template(template)
# render the template and its content
html_content = htmly.render(d)
subject = "Subject"
from_email = "fromthisemail#domain.com"
# HERE you add the emails to wich you want to send
to = [email1]
to.append(email2)
to.append(email3)
msg = EmailMultiAlternatives(subject, "", from_email, to)
msg.attach_alternative(html_content, "text/html")
msg.send()
Can I send an html formatted document as the body of an email and include an attachment?
send_mail() has an option for html_message but the EmailMessage class does not.
My understanding is that to send an attachment, I need to use the EmailMessage class to use the attach_file method.
Am I missing something? I thought send_mail() uses the EmailMessage class, so why do these two features seem mutually exclusive?
Check out EmailMultiAlternatives it has an attach function that you can use for this purpose.
Here's an example of how to use it:
from django.core.mail import EmailMultiAlternatives
subject = request.POST.get('subject', '')
message = request.POST.get('message', '').encode("utf-8")
# Create an e-mail
email_message = EmailMultiAlternatives(
subject=subject,
body=message,
from_email=conn.username,
to=recipents,
bcc=bcc_recipents, # ['bcc#example.com'],
cc=cc_recipents,
headers = {'Reply-To': request.user.email},
connection = connection
)
email_message.attach_alternative(message, "text/html")
for a in matachments:
email_message.attach(a.name, a.document.read())
email_message.send()
I see that to have an html email, I can have html as the body, but I just need to change the content_subtype to html.
msg_body.content_subtype = "html"
Thanks for your help, it got me back to the right page to read in better detail.
In Django, I wish to have the send_email send the email to settings.MANAGERS and to the ticket issuer as well. So trying to set those in recipient_list porduced no luck. I am using class based view.
# views.py
...
from django.conf import settings
...
class TicketCreate(CreateView):
model = Ticket
fields = ['title', 'question_detail',]
raise_exception = False
success_url = reverse_lazy('ticket_list')
template_name = 'ticket/ticket_form.html'
def form_valid(self, form):
form.instance.owner = self.request.user
send_mail(
subject=form.cleaned_data.get('title').strip(),
message=form.cleaned_data.get('question_detail'),
from_email=form.cleaned_data.get('request.user.email'),
recipient_list=['settings.MANAGERS','request.user.email',],
)
return super(TicketCreate, self).form_valid(form)
# settings.py
...
MANAGERS = [
('Manager', 'email_id#somedomain.com'),
]
What would be the solution to achieve this?
MANAGERS is a tuple, and only the second element in each tuple is relevant. This will work:
sender = form.cleaned_data.get('request.user.email')
recipients = [a[1] for a in settings.MANAGERS]
recipients.append(sender)
send_mail(
subject=form.cleaned_data.get('title').strip(),
message=form.cleaned_data.get('question_detail'),
from_email=sender,
recipient_list=recipients,
)
The mail_managers function does most of this for you - the only difference being that it doesn't let you control the sender email (it uses SERVER_EMAIL).
Note that you should be very careful about sending mail on behalf of other people - it is only recommended if you control the sender's domain. Otherwise your messages have a good chance of being caught as spam, with the associated reputation risk for the sending server.
Thanks solarissmoke, Because I only let logged in users send the ticket and that all users are required to authenticate with valid email address, I assume users do NOT need to enter email addres again. So, get email from the user data and insert that into the ticket.
Therefore, I modified a bit like below and all work just cool now. Thanks again and you are right about spam stuff - all under my control.
sender=self.request.user.email
recipients = [a[1] for a in settings.MANAGERS]
recipients.append(sender)
send_mail(
subject=form.cleaned_data.get('title').strip(),
message=form.cleaned_data.get('question_detail'),
from_email=sender,
recipient_list=recipients,
)
I have a contact form at shantiyoga.ca/contact
With the view
def contact(request):
template = 'contact.html'
form = ContactForm(request.POST or None)
if form.is_valid(): # All validation rules pass
subject = form.cleaned_data['subject']
message = "%s\n\n%s" % (form.cleaned_data['message'], form.cleaned_data['sender'])
cc_myself = form.cleaned_data['cc_myself']
recipients = ['contact#shantiyoga.ca']
sender = form.cleaned_data['sender']
if cc_myself:
recipients.append(sender)
headers = {'Reply-To': form.cleaned_data['sender']}
from django.core.mail import send_mail
send_mail(subject,message,sender,recipients,headers)
return redirect('/thanks/')
return render_to_response(template, {'form': form, 'current':'contact'}, context_instance=RequestContext(request))
Which works fairly well. I'm not terribly sophisticated with Django and my Python skills are not quite up to snuff, so please bear with me if I step through this in a basic fashion.
I would like to clarify that there is no way for the form recipient (contact#shantiyoga.ca) to receive the contact form from the value of the email field (user entered). It will always be sent by the authenticated email in my settings.py, which at this point is my personal email?
A user fills out the contact form and hits submit, an email is sent to contact#shantiyoga.ca from my personal email, and if the user decides to cc themself, a copy of the email is sent to them, also from my personal email.
This is not ideal, should I create an email like contactform#shantiyoga.ca for my settings.py to send the email from?
Also, the headers = {'Reply-To': form.cleaned_data['sender']} does not appear to be doing anything and I can't seem to find documentation describing its proper usage, has anyone had success using this technique?
Thank you for your time,
Noah
I would like to clarify that there is no way for the form recipient (contact#shantiyoga.ca) to receive the contact form from the value of the email field (user entered). It will always be sent by the authenticated email in my settings.py, which at this point is my personal email?
You're setting the sender of the email to sender but using EMAIL_HOST, correct? If this is the case, be careful that your SMTP account will let you send email from users other than your domain. Normally, providing you have an authenticated account on that server, you'll be able to set the From: field to whatever you like.
So in short, this email will hit your inbox appearing to be from the sender variable. So when you hit reply, you'll be able to email them back, which is I think what you want. However, it will be sent using the SMTP server whose authentication details you provide. There is a disconnect between being able to send email (SMTP) and being able to receive it, which I think has got you confused.
I've never tried it, but to add extra headers I believe you need to use the EmailMessage object. According to the docs, you would:
e = EmailMessage(headers={'Reply-To':...
e.send()
Be careful doing this; specifically, be careful to strip out newlines in the reply to field. I do not know if the default clean methods would do this.
Finally, there isn't much wrong with your django/python at all. The only thing I'd say, by way of awareness, is not to use this:
return redirect('/thanks/')
but instead:
return HttpResponseRedirect(reverse('myapp.views.method',args=tuple,kwargs=dict))
This gives you the ability to not hardcode urls into your application. The reverse method will look them up from urls.py for you, so you can move your application around/change urls and it will still work.
Here is signature of send_mail from django documentation:
send_mail(subject, message, from_email, recipient_list, fail_silently=False, auth_user=None, auth_password=None, connection=None)
As you can see it does not have headers argument.
You will need to use EmailMessage object directly.
It would also be nice to remove email-formatting from view. I would write everything something more like this:
from django.core.mail.message import EmailMessage
from django.conf import settings
class ContactsEmailMessage(EmailMessage):
def __init__(self, sender, subject, message, cc_myself):
super(ContactEmailMessage, self).__init__(
subject=subject,
body=self._get_message(self, sender, message),
from=settings.DEFAULT_FROM_EMAIL,
to=settings.CONTACT_RECIPIENTS,
headers=self._get_headers(sender),
cc=(sender, ) if cc_myself else None
)
def _format_message(self, sender, message):
return "%s\n\n%s" % (sender, message)
def _get_headers(self, sender):
return {
'reply-to': sender
}
Now you can write clean and easy to read view:
from myproject.mail.message import ContactsEmailMessage, BadHeaderError
from django.core.exceptions import SuspiciousOperation
def contact(request):
...
form = ContactForm(request.POST or None)
if form.is_valid(): # All validation rules pass
try:
message = ContactsEmailMessage(**form.cleaned_data)
message.send()
except BadHeaderError:
# django will raise this error if user will try to pass suspicious new-line
# characters to "sender" or other fields. This is safe-guard from
# header injections
raise SuspiciousOperation()
return redirect('/thanks/')
...