How to send Email without using settings.py ? (smtp parameters in database) - django

I would like to be able to send emails with django but without using the email parameters in settings.py.
(EMAIL_HOST, EMAIL_USE_TLS, EMAIL_HOST_PASSWORD, etc ...)
These parameters are stored in db because they can be different depending on the user.
How to use these parameters in base to send emails and not those in settings.py ?
class EmailThread(threading.Thread):
"""
Class email (Thread)
"""
def __init__(self, subject, html_content, recipient_list):
self.subject = subject
self.recipient_list = recipient_list
self.html_content = html_content
threading.Thread.__init__(self)
def run (self):
msg = EmailMessage(self.subject,
self.html_content,
settings.EMAIL_HOST_USER,
self.recipient_list)
msg.content_subtype = "html"
msg.send()
def send_html_mail(subject, html_content, recipient_list):
"""
send an email asynchronous
"""
EmailThread(subject, html_content, recipient_list).start()
I can get the parameters using: email_params = EmailParameter.objects.get(user=request.user)
class EmailParameter(models.Model):
email_use_tls = models.BooleanField(_("email use tls"), default=True)
email_use_ssl = models.BooleanField(_("email use tls"), default=False)
email_host = models.URLField(_("email host"), max_length=200)
email_host_user = models.CharField(_("email host user"), max_length=200)
email_host_password = models.CharField(_("email host password"), max_length=200)
email_port = models.PositiveIntegerField(_("email port"))
default_from_email = models.EmailField(_("default from email"), max_length=200)
signature = models.TextField(_("signature"))
user = models.ForeignKey(
User,
verbose_name = _("user"),
related_name = "user_email_parameter",
on_delete=models.CASCADE
)

Just move all necessary parameters inside class instance and use it instead of settings.XXX:
class EmailThread(threading.Thread):
def __init__(self, subject, html_content, recipient_list, email_host_user):
self.subject = subject
self.recipient_list = recipient_list
self.html_content = html_content
# set parameter to instance
self.email_host_user = email_host_user
threading.Thread.__init__(self)
def run (self):
msg = EmailMessage(self.subject,
self.html_content,
# use instance parameter
self.email_host_user,
self.recipient_list)
msg.content_subtype = "html"
msg.send()
# add email_host_user to be able set it when call mail send process
def send_html_mail(subject, html_content, recipient_list, email_host_user):
EmailThread(subject, html_content, recipient_list, email_host_user).start()
Now you able to send mail with custom parameters:
e_h_u = EmailParameter.objects.get(user=request.user).email_host_user
send_html_mail(subject, html_content, recipient_list, e_h_u)

Related

django related to host mail

Problem is related to host mail address as it cannot be changed and because of fixed host name, the sender’s mail address is not being updated after updating it several times
The problem with SendinBlue is that it does not allow us to use attachments with mail and ignores the attachments every time while sending an email
While using react for frontend, it saved the data from mails and does not send the mail from the backend through API.
def send_mail(request):
# form = emailssForm()
if request.method == 'POST':
name = request.POST.get('name')
email = request.POST.get('email')
message = request.POST.get('message')
subject = request.POST.get('subject')
from_email = request.POST.get('from_email')
# file = request.POST.get('file')
template = loader.get_template('contact_form.txt')
context = {
'name': name,
'email': email,
'message': message,
'subject': subject,
'from_email':from_email,
# 'file' : file,
}
message = template.render(context)
email = EmailMultiAlternatives(
"Uthara Print", email,message,
"Compny " + "Uthara Print",
['pandayharsh472#gmail.com',email]
)
# msg = EmailMultiAlternatives(
# subject,message,name,[from_email],
# )
email.content_subtype = 'html'
file = request.FILES['file']
email.attach(file.name, file.read(), file.content_type)
email.send()
messages.success(request, 'Message sent successfully ! I will ansewr you as soon as possibile....')
return HttpResponseRedirect('/')
SETTING.PY.............................................................
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = 'smtp.gmail.com'
EMAIL_PORT = 587
EMAIL_HOST_USER = 'GMAIL_HOST_USER'
EMAIL_HOST_PASSWORD = 'PASSWORD'
EMAIL_USE_TLS = True
EMAIL_USE_SSL = False`

How to email specific users when a new question is registered

I would like to send an email to all teachers who teach subjects related to a new question (whether it is created by the admin panel or the question creation form) so that they can approve the question. How to do this?
models.py
class Usuario(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE,verbose_name="Usuário")
USUARIO_CHOICES = (
(UM,'Aluno'),
(DOIS,'Professor'),
)
tipoUsuario = models.IntegerField('Tipo de Usuário',choices=USUARIO_CHOICES,default=1)
class Questao(models.Model):
aOpcao = models.CharField(max_length=500,null=False,blank=True,verbose_name="Letra a")
bOpcao = models.CharField(max_length=500,null=False,blank=True,verbose_name="Letra b")
cOpcao = models.CharField(max_length=500,null=False,blank=True,verbose_name="Letra c")
dOpcao = models.CharField(max_length=500,null=False,blank=True,verbose_name="Letra d")
eOpcao = models.CharField(max_length=500,null=False,blank=True,verbose_name="Letra e")
settings.py
EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
EMAIL_HOST = 'smtp.gmail.com'
EMAIL_PORT = 587
EMAIL_HOST_USER = 'myemail#outlook.com'
EMAIL_HOST_PASSWORD = 'Mypassword'
EMAIL_USE_TLS = True
DEFAULT_FROM_EMAIL = 'MySite <myemail#outlook.com>'
views.py
def add_questoes(request):
if request.method == 'POST': # If the form has been submitted...
form = QuestaoForm(request.POST) # A form bound to the POST data
if form.is_valid(): # All validation rules pass
form.save()
subject = 'Questão adicionada'
message = 'Há uma nova questão adicionada'
recepient = str(sub['Email'].value())
send_mail(subject,
message, EMAIL_HOST_USER, [recepient], fail_silently = False)
return redirect('/') # Redirect after POST
else:
form = QuestaoForm() # An unbound form
return render(request, 'polls/add_question.html', {'form': form})
forms.py
class QuestaoForm(forms.ModelForm):
aOpcao = forms.CharField(max_length=500,label="Letra a")
bOpcao = forms.CharField(max_length=500,label="Letra b")
cOpcao= forms.CharField(max_length=500,label="Letra c")
dOpcao = forms.CharField(max_length=500,label="Letra d")
eOpcao = forms.CharField(max_length=500,label="Letra e")
class Meta:
model = Questao
fields = '__all__'
Take a look at this documentation:
https://docs.djangoproject.com/en/2.2/ref/signals/
Django post save signals are a great way to execute code after specific DB operation. In your case I would think you would need to create a post_save signal which triggers the sending of the email.

How to write test case for sending email

Here is the simple view for creating user and staff model.After creating user and staff, it sends the html email to the user's email to fill up the details and the view works fine.
Now I want to write test case for this view and tried like this below but i got stuck on how can i write test to check whether the email will be sent or not after saving staff model, to the users.
models.py
class Staff(models.Model):
user = models.OneToOneField(get_user_model(), on_delete=models.CASCADE, related_name='staff')
name = models.CharField(max_length=255, blank=True, null=True)
organization = models.ForeignKey(Organization, on_delete=models.SET_NULL,related_name='staff')
position = models.ForeignKey(Position, on_delete=models.SET_NULL,related_name='staff')
.......
views.py
def register_staff(request):
form = RegisterStaffForm()
if request.method == 'POST':
form = RegisterStaffForm(request.POST)
if form.is_valid():
name = form.cleaned_data['name']
organization = form.cleaned_data['organization']
position = form.cleaned_data['position']
......
user = form.save(commit=False)
user.is_staff = True
user.is_active = True
user.save()
# creating staff model with user data
Staff.objects.create(user=user, name=name, organization=organization, position=position,....)
# sending html_email to the user
config = EmailConfiguration.objects.order_by('-date').first()
backend = EmailBackend(host=config.email_host, port=config.email_port, username=config.email_host_user,
password=config.email_host_password, use_tls=config.email_use_tls)
subject, from_email, to = "Staff Details", config.email_host_user, user.email
text_content = "Staff Details "
site = get_current_site(request)
html_content = render_to_string('send_email.html',
{'user': user, 'site_domain': site,})
msg = EmailMultiAlternatives(subject, text_content, from_email, [to],connection=backend)
msg.attach_alternative(html_content, "text/html")
msg.send()
tests.py
class StaffTestCase(TestCase):
def setUp(self):
self.position = Position.objects.create(title='Developer')
self.org = Organization.objects.create(name='name')
self.user = get_user_model().objects.create_user(username='username01',password='Admin#321',email='abc#xyz.com',is_staff=True)
self.staff = Staff.objects.create(user=self.user,position=self.position,organization=self.org,name='Julia')
self.client = Client()
def test_view_staffs(self):
self.client.login(username='username01', password='Admin#321')
response = self.client.get(reverse('app:view_staff_users'))
self.assertEqual(response.status_code, 200)
def add_staff(self):
self.client.login(username='username01', password='Admin#321')
url = reverse('app:register_staff')
response = self.client.post(url, {'user': self.user,'organization':'name1','position':'Designer','name':'Mark'})
self.assertEqual(response.status_code, 302)
def check_email_will_sent_or_not(self):
??
Django provides tools to test the sending of emails, but from my understanding, these only work with the default email backend configured in your settings file.
That leaves you with four options:
figure out if you can monkeypatch your view to use locmem backend in testing
mock EmailBackend in your register_staff view and check if its send_messages function is called.
spin up a dummy SMTP server and check if it receives the messages
use valid credentials to actually send the emails to addresses you control and check if the email is received
The options 3 & 4 give you the most confidence that your email sending really works, but they might turn out to be slow and brittle and actually test the email sending code of Django itself. I would go with option 2.

I am not getting emails from my contact form

Hey guys I am trying to make my contact form in django 2.1 which will send emails to me from the sender but I don,t know why it,s not sending me the email I was supposed to receive
views.py
def index(request):
queryset = Post.objects.filter(featured = True)
if request.method == 'POST':
name = request.POST.get('name')
email = request.POST.get('email')
subject = request.POST.get('subject')
message = request.POST.get('message')
subject = 'Message from ubaidparvaiz.com recieved'
from_email = settings.DEFAULT_FROM_EMAIL
to_email = [settings.DEFAULT_FROM_EMAIL]
context = {'user':name,
'email':email,
'message':message,
'subject':subject
}
contact_message = get_template('app/contact_message.txt').render(context)
send_mail(subject,message,from_email,to_email,fail_silently = True)
return redirect('index')
return render(request,'app/index.html',{'object':queryset})
settings.py
SEND_GRID_API_KEY = 'API key'
EMAIL_HOST = 'smtp.sendgrid.net'
EMAIL_HOST_USER = 'ubaidparvaiz'
EMAIL_HOST_PASSWORD = '.py/r^admin1'
EMAIL_PORT = 587
EMAIL_USE_TLS = True
DEFAULT_FROM_EMAIL = 'ubaidparvez4#gmail.com'
ACCOUNT_EMAIL_SUBJECT_PREFIX = 'Contact email received from my blog'
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
contact_message.txt
You recieved a message,Don,t panic ..Keep it normal
The sender,s name : {{user}}
They sender,s email : {{email}}
The sender,s subject : {{subject}}
This is what he states : {{message}}
Thank You
I recommend you check your spam folder. Gmail usually filters emails coming from untrusted sources.

Django: send email on form submition

I need to send an email after user submits a form on my page (this is still in development, but it'll be in production soon).
I've read this other answer but after my form is submitted I'm not reciving any email (I've used my personal email as the sender and the receiver, for testing).
What I need to modify?
PLUS: How to send images on emails? Any tutorial on this? I need to send professional emails after form submition.
settings.py
EMAIL_HOST = 'smtp.gmail.com' # since you are using a gmail account
EMAIL_PORT = 587 # Gmail SMTP port for TLS
EMAIL_USE_TLS = True
EMAIL_HOST_USER = 'oma.oma#gmail.com' #Not my actual email
EMAIL_HOST_PASSWORD = 'MyPassword' #Not my actual password
views.py:
# here we are going to use CreateView to save the Third step ModelForm
class StepThreeView(CreateView):
form_class = StepThreeForm
template_name = 'main_app/step-three.html'
success_url = '/'
def form_valid(self, form):
form.instance.tamanios = self.request.session.get('tamanios') # get tamanios from session
form.instance.cantidades = self.request.session.get('cantidades') # get cantidades from session
del self.request.session['cantidades'] # delete cantidades value from session
del self.request.session['tamanios'] # delete tamanios value from session
self.request.session.modified = True
return super(StepThreeView, self).form_valid(form)
form.py:
from django.core.mail import send_mail
class StepThreeForm(forms.ModelForm):
instrucciones = forms.CharField(widget=forms.Textarea)
class Meta:
model = TamaniosCantidades
fields = ('imagenes', 'instrucciones')
def __init__(self, *args, **kwargs):
super(StepThreeForm, self).__init__(*args, **kwargs)
self.fields['instrucciones'].required = False
def send_email(self):
send_mail('Django Test', 'My message', 'oma.oma#gmail.com',
['oma.oma#gmail.com'], fail_silently=False)
You can override the save method like this in your Last Form:
class StepThreeForm(forms.ModelForm):
def save(self, commit=True):
instance = super(StepThreeForm, self).save(commit=commit)
self.send_email()
return instance
def send_email(self):
image = self.cleaned_data.get('imagenes', None)
msg = EmailMessage(
'Hello',
'Body goes here',
'from#example.com',
['to1#example.com', 'to2#example.com'],
headers={'Message-ID': 'foo'},
)
msg.content_subtype = "html"
if image:
mime_image = MIMEImage(image.read())
mime_image.add_header('Content-ID', '<image>')
msg.attach(mime_image)
msg.send()
You can check this SO Answer for more details on how to send image from Django