def test_connection_kwargs_overrides_settings(self): connection = get_connection('anymail.backends.mailgun.MailgunBackend') self.assertEqual(connection.api_key, 'api_key_from_settings') connection = get_connection('anymail.backends.mailgun.MailgunBackend', api_key='api_key_from_kwargs') self.assertEqual(connection.api_key, 'api_key_from_kwargs')
def test_file_sessions(self): """Make sure opening a connection creates a new file""" msg = EmailMessage('Subject', 'Content', '*****@*****.**', ['*****@*****.**'], headers={'From': '*****@*****.**'}) connection = mail.get_connection() connection.send_messages([msg]) self.assertEqual(len(os.listdir(self.tmp_dir)), 1) with open(os.path.join(self.tmp_dir, os.listdir(self.tmp_dir)[0]), 'rb') as fp: message = message_from_binary_file(fp) self.assertEqual(message.get_content_type(), 'text/plain') self.assertEqual(message.get('subject'), 'Subject') self.assertEqual(message.get('from'), '*****@*****.**') self.assertEqual(message.get('to'), '*****@*****.**') connection2 = mail.get_connection() connection2.send_messages([msg]) self.assertEqual(len(os.listdir(self.tmp_dir)), 2) connection.send_messages([msg]) self.assertEqual(len(os.listdir(self.tmp_dir)), 2) msg.connection = mail.get_connection() self.assertTrue(connection.open()) msg.send() self.assertEqual(len(os.listdir(self.tmp_dir)), 3) msg.send() self.assertEqual(len(os.listdir(self.tmp_dir)), 3) connection.close()
def test_file_sessions(self): """Make sure opening a connection creates a new file""" msg = EmailMessage( "Subject", "Content", "*****@*****.**", ["*****@*****.**"], headers={"From": "*****@*****.**"} ) connection = mail.get_connection() connection.send_messages([msg]) self.assertEqual(len(os.listdir(self.tmp_dir)), 1) message = email.message_from_file(open(os.path.join(self.tmp_dir, os.listdir(self.tmp_dir)[0]))) self.assertEqual(message.get_content_type(), "text/plain") self.assertEqual(message.get("subject"), "Subject") self.assertEqual(message.get("from"), "*****@*****.**") self.assertEqual(message.get("to"), "*****@*****.**") connection2 = mail.get_connection() connection2.send_messages([msg]) self.assertEqual(len(os.listdir(self.tmp_dir)), 2) connection.send_messages([msg]) self.assertEqual(len(os.listdir(self.tmp_dir)), 2) msg.connection = mail.get_connection() self.assertTrue(connection.open()) msg.send() self.assertEqual(len(os.listdir(self.tmp_dir)), 3) msg.send() self.assertEqual(len(os.listdir(self.tmp_dir)), 3)
def send_email(self, args, options): if options['file_back_end']: backend = get_connection(FILEBASED_BACKEND, file_path=options['file_back_end']) elif options['console_back_end']: backend = get_connection(CONSOLE_BACKEND) else: backend = get_connection(SMTP_BACKEND) passwords = defaultdict(lambda: '') if os.path.isfile(options['passwords_file']): with open(options['passwords_file'], 'r') as passwords_file: p_reader = csv.reader(passwords_file) for row in p_reader: passwords[row[-2]] = row[-1] message_template = None if os.path.isfile(options['message_file']): with open(options['message_file'], 'r') as message_file: message_template = Template(message_file.read().decode('utf-8')) if options['all']: users = User.objects.all() elif options['input_file']: with open(options['input_file'], 'r') as usernames_file: usernames = [x.rstrip() for x in usernames_file.readlines()] users = User.objects.filter(username__in=usernames) else: users = User.objects.filter(username__in=args) for user in users: message = self.make_invite(user, {'password': passwords[user.username]}, message_template) send_mail(options['subject'], message, options['from'], [user.email], fail_silently=False, connection=backend)
def test_connection_arg(self): """Test connection argument to send_mail(), et. al.""" mail.outbox = [] # Send using non-default connection connection = mail.get_connection("regressiontests.mail.custombackend.EmailBackend") send_mail("Subject", "Content", "*****@*****.**", ["*****@*****.**"], connection=connection) self.assertEqual(mail.outbox, []) self.assertEqual(len(connection.test_outbox), 1) self.assertEqual(connection.test_outbox[0].subject, "Subject") connection = mail.get_connection("regressiontests.mail.custombackend.EmailBackend") send_mass_mail( [ ("Subject1", "Content1", "*****@*****.**", ["*****@*****.**"]), ("Subject2", "Content2", "*****@*****.**", ["*****@*****.**"]), ], connection=connection, ) self.assertEqual(mail.outbox, []) self.assertEqual(len(connection.test_outbox), 2) self.assertEqual(connection.test_outbox[0].subject, "Subject1") self.assertEqual(connection.test_outbox[1].subject, "Subject2") connection = mail.get_connection("regressiontests.mail.custombackend.EmailBackend") mail_admins("Admin message", "Content", connection=connection) self.assertEqual(mail.outbox, []) self.assertEqual(len(connection.test_outbox), 1) self.assertEqual(connection.test_outbox[0].subject, "[Django] Admin message") connection = mail.get_connection("regressiontests.mail.custombackend.EmailBackend") mail_managers("Manager message", "Content", connection=connection) self.assertEqual(mail.outbox, []) self.assertEqual(len(connection.test_outbox), 1) self.assertEqual(connection.test_outbox[0].subject, "[Django] Manager message")
def test_connection_kwargs_overrides_settings(self): """Can override settings file in get_connection""" backend = get_connection() self.assertEqual(backend.sample_setting, 'setting_from_settings') backend = get_connection(sample_setting='setting_from_kwargs') self.assertEqual(backend.sample_setting, 'setting_from_kwargs')
def send_raw_email(recipients, subject, text, html): """ Sends and multi-part (text and optionally HTML) email to a list of users or email addresses """ to_addresses = [] for recipient in recipients: if isinstance(recipient, User): to_addresses.append(recipient.email) elif isinstance(recipient, six.string_types): to_addresses.append(recipient) else: # pragma: no cover raise ValueError("Email recipients must users or email addresses") from_address = getattr(settings, 'DEFAULT_FROM_EMAIL', '*****@*****.**') if getattr(settings, 'SEND_EMAILS', False): # send individual messages so as to not leak users email addresses, but use bulk send operation for speed messages = [] for to_address in to_addresses: message = EmailMultiAlternatives(subject, text, from_email=from_address, to=[to_address]) if html: message.attach_alternative(html, "text/html") messages.append(message) get_connection().send_messages(messages) else: # pragma: no cover print("FAKE SENDING this email to %s:" % ", ".join(to_addresses)) print("--------------------------------------- text -----------------------------------------") print(text) if html: print("--------------------------------------- html -----------------------------------------") print(html)
def test_email_msg_uses_crlf(self): """#23063 -- Test that RFC-compliant messages are sent over SMTP.""" send = SMTP.send try: smtp_messages = [] def mock_send(self, s): smtp_messages.append(s) return send(self, s) SMTP.send = mock_send email = EmailMessage('Subject', 'Content', '*****@*****.**', ['*****@*****.**']) mail.get_connection().send_messages([email]) # Find the actual message msg = None for i, m in enumerate(smtp_messages): if m[:4] == 'data': msg = smtp_messages[i + 1] break self.assertTrue(msg) if PY3: msg = msg.decode('utf-8') # Ensure that the message only contains CRLF and not combinations of CRLF, LF, and CR. msg = msg.replace('\r\n', '') self.assertNotIn('\r', msg) self.assertNotIn('\n', msg) finally: SMTP.send = send
def save(self, *args, **kwargs): super(Projeto, self).save(*args, **kwargs) ## ENVIA 1 EMAIL SOMENTE SE FOI APROVADO O CADASTRO ## if self.situacao == 'Aprovado' and self.enviar == 'Enviar': enviar = User.objects.get(username__iexact=self.criador) subject = 'Projeto Feitec' message = 'O projeto %s foi será no \nBloco: %s \nSala: %s' %(self.nomeProj,self.blocoProj,self.salaProj) from_email = ''#email remetente connection = get_connection(username = '', password ='')#email e senha de conexão send_email = EmailMessage(subject, message , from_email, [enviar.email], connection = connection) send_email.content_subtype = "html" send_email.send() if (self.situacao == 'Aprovado' or self.situacao == 'Reprovado') and self.enviar == 'Pendente': enviar = User.objects.get(username__iexact=self.criador) subject = 'Projeto Feitec' message = 'O projeto %s foi %s!' %(self.nomeProj,self.situacao) from_email = ''#email remetente connection = get_connection(username = '', password ='')#email e senha de conexão send_email = EmailMessage(subject, message , from_email, [enviar.email], connection = connection) send_email.content_subtype = "html" send_email.send() if self.situacao == 'Enviado': enviar = User.objects.get(username__iexact=self.criador) subject = 'Projeto Feitec' message = 'O projeto %s foi enviado com sucesso. Aguarde a avaliação do próprio' %(self.nomeProj) from_email = ''#email remetente connection = get_connection(username = '', password ='')#email e senha de conexão send_email = EmailMessage(subject, message , from_email, [enviar.email], connection = connection) send_email.content_subtype = "html" send_email.send()
def test_connection_arg(self): """Test connection argument to send_mail(), et. al.""" mail.outbox = [] # Send using non-default connection connection = mail.get_connection('mail.custombackend.EmailBackend') send_mail('Subject', 'Content', '*****@*****.**', ['*****@*****.**'], connection=connection) self.assertEqual(mail.outbox, []) self.assertEqual(len(connection.test_outbox), 1) self.assertEqual(connection.test_outbox[0].subject, 'Subject') connection = mail.get_connection('mail.custombackend.EmailBackend') send_mass_mail([ ('Subject1', 'Content1', '*****@*****.**', ['*****@*****.**']), ('Subject2', 'Content2', '*****@*****.**', ['*****@*****.**']), ], connection=connection) self.assertEqual(mail.outbox, []) self.assertEqual(len(connection.test_outbox), 2) self.assertEqual(connection.test_outbox[0].subject, 'Subject1') self.assertEqual(connection.test_outbox[1].subject, 'Subject2') connection = mail.get_connection('mail.custombackend.EmailBackend') mail_admins('Admin message', 'Content', connection=connection) self.assertEqual(mail.outbox, []) self.assertEqual(len(connection.test_outbox), 1) self.assertEqual(connection.test_outbox[0].subject, '[Django] Admin message') connection = mail.get_connection('mail.custombackend.EmailBackend') mail_managers('Manager message', 'Content', connection=connection) self.assertEqual(mail.outbox, []) self.assertEqual(len(connection.test_outbox), 1) self.assertEqual(connection.test_outbox[0].subject, '[Django] Manager message')
def test_missing_api_key(self): with self.assertRaises(AnymailConfigurationError) as cm: mail.get_connection() # this init's SparkPost without actually trying to send anything errmsg = str(cm.exception) # Make sure the error mentions the different places to set the key self.assertRegex(errmsg, r'\bSPARKPOST_API_KEY\b') self.assertRegex(errmsg, r'\bANYMAIL_SPARKPOST_API_KEY\b')
def test_message_cc_header(self): """ Regression test for #7722 """ email = EmailMessage('Subject', 'Content', '*****@*****.**', ['*****@*****.**'], cc=['*****@*****.**']) mail.get_connection().send_messages([email]) message = self.get_the_message() self.assertStartsWith(message.as_string(), b'Content-Type: text/plain; charset="utf-8"\nMIME-Version: 1.0\nContent-Transfer-Encoding: 7bit\nSubject: Subject\nFrom: [email protected]\nTo: [email protected]\nCc: [email protected]\nDate: ')
def test_missing_setting(self): """Settings without defaults must be provided""" with self.assertRaises(AnymailConfigurationError) as cm: get_connection() self.assertIsInstance(cm.exception, ImproperlyConfigured) # Django consistency errmsg = str(cm.exception) self.assertRegex(errmsg, r'\bTEST_SAMPLE_SETTING\b') self.assertRegex(errmsg, r'\bANYMAIL_TEST_SAMPLE_SETTING\b')
def send_all(block_size=500, backend=None): """ Send all non-deferred messages in the queue. A lock file is used to ensure that this process can not be started again while it is already running. The ``block_size`` argument allows for queued messages to be iterated in blocks, allowing new prioritised messages to be inserted during iteration of a large number of queued messages. """ lock = FileLock(LOCK_PATH) logger.debug("Acquiring lock...") try: # lockfile has a bug dealing with a negative LOCK_WAIT_TIMEOUT (which # is the default if it's not provided) systems which use a LinkFileLock # so ensure that it is never a negative number. lock.acquire(settings.LOCK_WAIT_TIMEOUT or 0) #lock.acquire(settings.LOCK_WAIT_TIMEOUT) except AlreadyLocked: logger.debug("Lock already in place. Exiting.") return except LockTimeout: logger.debug("Waiting for the lock timed out. Exiting.") return logger.debug("Lock acquired.") start_time = time.time() sent = deferred = skipped = 0 try: if constants.EMAIL_BACKEND_SUPPORT: connection = get_connection(backend=backend) else: connection = get_connection() blacklist = models.Blacklist.objects.values_list('email', flat=True) connection.open() for message in _message_queue(block_size): try: result = send_queued_message(message, smtp_connection=connection, blacklist=blacklist) except Exception, e: result = constants.RESULT_FAILED logger.error(e) if result == constants.RESULT_SENT: sent += 1 elif result == constants.RESULT_FAILED: deferred += 1 elif result == constants.RESULT_SKIPPED: skipped += 1 connection.close()
def test_username_password_kwargs_overrides(self): # Additional checks for username and password, which are special-cased # because of Django core mail function defaults. connection = get_connection('anymail.backends.sendgrid.SendGridBackend') self.assertEqual(connection.username, 'username_from_settings') self.assertEqual(connection.password, 'password_from_settings') connection = get_connection('anymail.backends.sendgrid.SendGridBackend', username='******', password='******') self.assertEqual(connection.username, 'username_from_kwargs') self.assertEqual(connection.password, 'password_from_kwargs')
def send_all(block_size=500, backend=None): """ Send all non-deferred messages in the queue. A lock file is used to ensure that this process can not be started again while it is already running. The ``block_size`` argument allows for queued messages to be iterated in blocks, allowing new prioritised messages to be inserted during iteration of a large number of queued messages. """ logger.debug("Acquiring lock...") try: lock = LockFile(LOCK_PATH) except LockError: logger.debug("Lock already in place. Exiting.") return logger.debug("Lock acquired.") start_time = time.time() sent = deferred = skipped = 0 try: if constants.EMAIL_BACKEND_SUPPORT: connection = get_connection(backend=backend) else: connection = get_connection() blacklist = models.Blacklist.objects.values_list('email', flat=True) connection.open() for message in _message_queue(block_size): result = send_queued_message(message, smtp_connection=connection, blacklist=blacklist) if result == constants.RESULT_SENT: sent += 1 elif result == constants.RESULT_FAILED: deferred += 1 elif result == constants.RESULT_SKIPPED: skipped += 1 connection.close() finally: logger.debug("Releasing lock...") lock.close() logger.debug("Lock released.") logger.debug("") if sent or deferred or skipped: log = logger.warning else: log = logger.info log("%s sent, %s deferred, %s skipped." % (sent, deferred, skipped)) logger.debug("Completed in %.2f seconds." % (time.time() - start_time))
def test_username_password_kwargs_overrides(self): """Overrides for 'username' and 'password' should work like other overrides""" # These are special-cased because of default args in Django core mail functions. # (Use the SendGrid v2 backend, which has settings named 'username' and 'password'.) backend = get_connection('anymail.backends.sendgrid_v2.EmailBackend') self.assertEqual(backend.username, 'username_from_settings') self.assertEqual(backend.password, 'password_from_settings') backend = get_connection('anymail.backends.sendgrid_v2.EmailBackend', username='******', password='******') self.assertEqual(backend.username, 'username_from_kwargs') self.assertEqual(backend.password, 'password_from_kwargs')
def send_mail_to_adjs(round): tournament = round.tournament draw = round.debate_set_with_prefetches(speakers=False, divisions=False).all() use_codes = use_team_code_names(tournament, False) subject = Template(tournament.pref('adj_email_subject_line')) body = Template(tournament.pref('adj_email_message')) messages = [] adj_position_names = { AdjudicatorAllocation.POSITION_CHAIR: _("the chair"), AdjudicatorAllocation.POSITION_ONLY: _("the only"), AdjudicatorAllocation.POSITION_PANELLIST: _("a panellist"), AdjudicatorAllocation.POSITION_TRAINEE: _("a trainee"), } def _assemble_panel(adjs): adj_string = [] for adj, pos in adjs: adj_string.append("%s (%s)" % (adj.name, adj_position_names[pos])) return ", ".join(adj_string) for debate in draw: matchup = debate.matchup_codes if use_codes else debate.matchup context = { 'ROUND': round.name, 'VENUE': debate.venue.display_name if debate.venue is not None else _("TBA"), 'PANEL': _assemble_panel(debate.adjudicators.with_positions()), 'DRAW': matchup } for adj, pos in debate.adjudicators.with_positions(): if adj.email is None: continue context_user = context.copy() context_user['USER'] = adj.name context_user['POSITION'] = adj_position_names[pos] messages.append(TournamentEmailMessage(subject, body, tournament, round, SentMessageRecord.EVENT_TYPE_DRAW, adj, context_user)) try: get_connection().send_messages(messages) except SMTPException: logger.exception("Failed to send adjudicator e-mails") raise except ConnectionError: logger.exception("Connection error sending adjudicator e-mails") raise else: SentMessageRecord.objects.bulk_create([message.as_sent_record() for message in messages])
def send(self, retries=0): if self.to == []: logging.warn('No recipients set for email "%s"' % self.subject) global connection if connection is None: connection = mail.get_connection() # Use default email connection try: connection.send_messages([self]) except smtplib.SMTPServerDisconnected as e: if retries == connect_retires_max: raise e connection = mail.get_connection() # Use default email connection self.send(retries + 1)
def daily_update(experiment, debug=False, round_data=None, **kwargs): """ Triggered by round_ended_handler in experiment/lighterprints/signals.py, uses experiment.current_round_data if not explicitly set which assumes that the experiment has *not* advanced to the next round yet. """ all_messages = None with transaction.atomic(): round_data = experiment.current_round_data if round_data is None else round_data logger.debug("sending summary emails to %s for round %s", experiment, round_data) group_scores = GroupScores(experiment, round_data=round_data, groups=list(experiment.groups)) all_messages = list(group_scores.generate_daily_update_messages()) if not debug and all_messages: logger.debug("sending %s generated emails for lighter footprints", len(all_messages)) mail.get_connection().send_messages(all_messages)
def send_mass_mail_wrapper(subject, message, recipients, html_content=False): mails = [] content = message if html_content: content = "" for to in recipients: email = EmailMultiAlternatives(subject, content, settings.DEFAULT_FROM_EMAIL, [to]) if html_content: email.attach_alternative(message, "text/html") mails.append(email) try: get_connection().send_messages(mails) except IOError as ex: logger.error('The massive email "%s" to %s could not be sent because of %s' % (subject, recipients, str(ex)))
def send_message(message_id): message = Message.objects.get(id=message_id) if not message: return msg = EmailMultiAlternatives( subject=message.subject, body=message.content, from_email=message.sender, to=message.to, ) if message.html_content: msg.attach_alternative(message.html_content, "text/html") mailbox = message.mailbox if mailbox.type == MailBoxType.SMTP: backend = "django.core.mail.backends.smtp.EmailBackend" connection = get_connection( backend=backend, host=mailbox.smtp_host, port=int(mailbox.smtp_port), username=mailbox.smtp_username, password=mailbox.smtp_password, use_tls=mailbox.smtp_use_tls ) elif mailbox.type == MailBoxType.SES: backend = "django_ses.SESBackend" extra = {} if mailbox.enable_dkim and mailbox.dkim_key: extra['dkim_domain'] = str(mailbox.domain) extra['dkim_key'] = str(mailbox.dkim_key.replace('\r', '')) connection = get_connection( backend, aws_access_key=mailbox.aws_access_key, aws_secret_key=mailbox.aws_access_secret_key, **extra) else: return msg.connection = connection msg.send(fail_silently=False) message.is_sent = True message.sent_at = datetime.now() message.save()
def test_custom_backend(self): """Test custom backend defined in this suite.""" conn = mail.get_connection('mail.custombackend.EmailBackend') self.assertTrue(hasattr(conn, 'test_outbox')) email = EmailMessage('Subject', 'Content', '*****@*****.**', ['*****@*****.**'], headers={'From': '*****@*****.**'}) conn.send_messages([email]) self.assertEqual(len(conn.test_outbox), 1)
def test_send_unicode(self): email = EmailMessage('Chère maman', 'Je t\'aime très fort', '*****@*****.**', ['*****@*****.**']) num_sent = mail.get_connection().send_messages([email]) self.assertEqual(num_sent, 1) message = self.get_the_message() self.assertEqual(message["subject"], '=?utf-8?q?Ch=C3=A8re_maman?=') self.assertEqual(force_text(message.get_payload(decode=True)), 'Je t\'aime très fort')
def sendMailToContacts(name, html, text): # Get a list of all of the current contactees contacts = ContactEmail.objects.all() email_addresses = [] # Build E-Mail subject = str(name) + " has requested a Quote on SCCS" text_message = text html_message = html from_addr = "*****@*****.**" # Create List of e-mail addresses for address in contacts: email_addresses.append(address.email) try: # Get django e-mail settings connection = mail.get_connection() # Open E-Mail server connection connection.open() # Append RAW Text email_message = EmailMultiAlternatives(subject, text_message, from_addr, email_addresses, connection=connection) # Append HTML email_message.attach_alternative(html_message, "text/html") # Send Message email_message.send() connection.close() except Exception as err: connection.close() log(err)
def test_message_cc_header(self): """ Regression test for #7722 """ email = EmailMessage('Subject', 'Content', '*****@*****.**', ['*****@*****.**'], cc=['*****@*****.**']) mail.get_connection().send_messages([email]) message = self.get_the_message() self.assertMessageHasHeaders(message, { ('MIME-Version', '1.0'), ('Content-Type', 'text/plain; charset="utf-8"'), ('Content-Transfer-Encoding', '7bit'), ('Subject', 'Subject'), ('From', '*****@*****.**'), ('To', '*****@*****.**'), ('Cc', '*****@*****.**')}) self.assertIn('\nDate: ', message.as_string())
def test_arbitrary_keyword(self): """ Make sure that get_connection() accepts arbitrary keyword that might be used with custom backends. """ c = mail.get_connection(fail_silently=True, foo='bar') self.assertTrue(c.fail_silently)
def send_bill(self, request, queryset): for registration in queryset: if registration.billed: self.message_user( request, 'Some of the selected registrations have ' 'already been billed' ) return if not registration.bill_text: self.message_user( request, 'Some of the selected registration do not have bill text') return smtp_connection = get_connection() for registration in queryset: registration.bill_date = date.today() self.send_message( smtp_connection, 'Invoice for PyCon Finland %s' % settings.YEAR, registration.bill_text, registration, ) registration.billed = True registration.save()
def send_payment_notification(self, request, queryset): for registration in queryset: if not registration.billed: self.message_user( request, 'Some of the selected registrations ' 'have not been billed yet' ) return if registration.paid: self.message_user( request, 'Some of the selected registrations ' 'have paid' ) smtp_connection = get_connection() for registration in queryset: self.send_message( smtp_connection, 'Payment notification for PyCon Finland %s' % settings.YEAR, registration.notify_text, registration, ) registration.notified_date = date.today() registration.save()
def genericEmailAnnouncement(subject = "", body="", sender="", distribution_list=None, ): """ provides a bunch of default values for testing purposes ==> sends a test email to myself """ if not subject: subject = "See what's new with LiquidQuotes.com" if not body: body = 'Here is another message' if not sender: sender = "Liquid Quotes <*****@*****.**>" if not distribution_list: distribution_list = ['*****@*****.**'] connection = mail.get_connection() connection.open() for emailAddress in distribution_list: print >> sys.stderr, "Emailing %s" % emailAddress try: email1 = mail.EmailMessage(subject, body, sender, [emailAddress], connection=connection) email1.send() except: print "Error with %s" % emailAddress
def send_mosaico_email( code, subject, from_email, recipients, recipient_type="to", bindings=None, connection=None, backend=None, fail_silently=False, preferences_link=True, reply_to=None, attachments=None, ): """Send an email from a Mosaico template :param code: the code identifying the Mosaico template :param subject: the subject line of the email :param from_email: the address from which the email is to be sent :param recipients: a list of recipients to which the email will be send; alternatively, a single address :param bindings: a dictionary of replacements variables and their target values in the Mosaico template :param connection: an optional email server connection to use to send the emails :param backend: if no connection is given, an optional mail backend to use to send the emails :param fail_silently: whether any error should be raised, or just be ignored; by default it will raise :param gen_connection_params_function: a function that takes a recipient and generates connection params """ try: iter(recipients) except TypeError: recipients = [recipients] if recipient_type not in ["to", "cc", "bcc"]: raise ValueError("`recipient_type` must be to, cc or bcc") if bindings is None: bindings = {} if connection is None: connection = get_connection(backend, fail_silently) if preferences_link: bindings["preferences_link"] = bindings["PREFERENCES_LINK"] = front_url( "contact" ) bindings["unsubscribe_link"] = bindings["UNSUBSCRIBE_LINK"] = front_url( "unsubscribe" ) link_bindings = { key: value for key, value in bindings.items() if is_front_url(value) } html_template = loader.get_template(f"mail_templates/{code}.html") try: text_template = loader.get_template(f"mail_templates/{code}.txt") except TemplateDoesNotExist: text_template = None with connection: for recipient in recipients: # recipient can be either a Person or an email address if isinstance(recipient, Person): if recipient.role is not None and not recipient.role.is_active: continue connection_params = generate_token_params(recipient) for key, value in link_bindings.items(): if isinstance(value, AutoLoginUrl): bindings[key] = add_params_to_urls(value, connection_params) bindings["MERGE_LOGIN"] = urlencode(connection_params) context = get_context_from_bindings(code, recipient, bindings) html_message = html_template.render(context=context) text_message = ( text_template.render( context={k: conditional_html_to_text(v) for k, v in context.items()} ) if text_template else generate_plain_text(html_message) ) email = EmailMultiAlternatives( subject=subject, body=text_message, from_email=from_email, reply_to=reply_to, connection=connection, **{ recipient_type: [ recipient.email if isinstance(recipient, Person) else recipient ] }, ) email.attach_alternative(html_message, "text/html") if attachments is not None: for attachment in attachments: if isinstance(attachment, MIMEBase): email.attach(attachment) elif isinstance(attachment, dict): email.attach(**attachment) else: email.attach(*attachment) email.send(fail_silently=fail_silently)
def send_batch_emails(emails): connection = mail.get_connection() connection.send_messages(emails)
def register(request): registered = False # If it's a HTTP POST, we'll process the form data. if request.method == 'POST': # Attempt to grab information from the raw form information. username = request.POST['username'] email = request.POST['email'] user_form = UserForm(data=request.POST) # If the form is valid... if user_form.is_valid(): # Save the user's form data to the database. user = user_form.save() # Hash the password with the set_password method user.set_password(user.password) user.save() # Update our variable to tell the template registration was # successful. registered = True # START FOR DEVELOPMENT USE ONLY subject = 'Verify Email' email_body = 'Hello ' + username + ", click this <a href='http://127.0.0.1:8000/verify/" + \ email + "'>link</a> to verify your account" email_from = '*****@*****.**' with mail.get_connection() as connection: mail.EmailMessage( subject, email_body, email_from, [email], connection=connection, ).send() # END FOR DEVELOPMENT USE ONLY return HttpResponse( "Please check your email for a verification link for your account." ) else: # See if we have that username or email in the db user_username = User.objects.filter(username=username) user_email = User.objects.filter(email=email) if user_username & user_email: error = "That account already exists." elif user_username: error = "That username is already taken." elif user_email: error = "That email is already in use." else: error = 'Registration credentials are not valid. Please try again.' return render(request, 'register.html', { 'error': error, 'user_form': user_form, 'registered': registered }) # Not a HTTP POST, so we render our form using our ModelForm instance. # These forms will be blank, ready for user input. else: user_form = UserForm() return render(request, 'register.html', { 'user_form': user_form, 'registered': registered })
def handle(self, *args, **options): connection = mail.get_connection() messages = self.get_emails() num_emails = connection.send_messages(messages) self.stdout.write( unicode(_(u'Foram enviados {0} emails\n'.format(num_emails))), )
def create( self, request=None, from_email=None, to=None, cc=None, bcc=None, reply_to=None, context=None, attachments=None, alternatives=None, fail_silently=True, auth_user=None, auth_password=None, connection=None, headers=None, noreply=False, language=None, subject=None, body=None, ): # NOQA site = Site.objects.get_current() subject_template = Template( self.translate( language=language).subject if subject is None else subject) body_template = Template( self.translate(language=language).body if body is None else body) context = {} if context is None else context context = Context(context) if request is None else RequestContext( request, context) connection = connection or get_connection( username=auth_user, password=auth_password, fail_silently=fail_silently, ) if isinstance(to, str): to = [to] elif self.default_to: to = self.default_to.split(",") if isinstance(cc, str): cc = [cc] elif self.default_cc: cc = self.default_cc.split(",") if isinstance(bcc, str): bcc = [bcc] elif self.default_bcc: bcc = self.default_bcc.split(",") if isinstance(reply_to, str): reply_to = [reply_to] elif self.default_reply_to: reply_to = self.default_reply_to.split(",") headers = headers = {} if headers is None else headers noreply = noreply or self.noreply if noreply and not reply_to and "Reply-to" not in headers: reply_to = ["noreply@%s" % site.domain] kwargs = { "subject": subject_template.render(context).replace("\n", ""), "body": body_template.render(context), "from_email": self.from_email if from_email is None else from_email, "to": to, "cc": cc, "bcc": bcc, "reply_to": reply_to, "headers": headers, "connection": connection, "attachments": attachments, "alternatives": alternatives, } email = EmailMultiAlternatives(**kwargs) if self.body_html: body_html_template = Template( self.translate(language=language).body_html) email.attach_alternative(body_html_template.render(context), "text/html") return email
from django.db.models.signals import post_save from django.core.mail import EmailMessage from django.core import mail from django.dispatch import receiver from .models import File from app.core.models import UUIDUser connection = mail.get_connection() connection.open() def file_create_post_save(sender, instance, created, **kwargs): user_adm = UUIDUser.objects.filter(is_staff=True).first() if created: email_user = mail.EmailMessage( 'Arquivo Enviado com Sucesso - Status Atual "Aguradando Impressão"', 'Caro, %s.\n\nInformamos que o arquivo "%s" foi recebido com sucesso, logo ele será impresso e você poderá pegar o arquivo pronto na mecanografia.\n\nAtenciosamente,\n%s\n\n\n\nEssa mensagem é automática, ok? Não é pra responder esse e-mail.' % (instance.user.first_name, instance.name, user_adm.first_name), '*****@*****.**', [instance.user.email], connection=connection, ) email_user.send() email_adm = mail.EmailMessage( 'Novo Arquivo Aguradando Impressão', 'O usuário %s enviou um novo arquivo para impressão.\n\nDetalhes da Solicitação:\nNome do Arquivo: %s\nQuantidade de Páginas: %i\nQuantidade de Cópias: %i\n\n\n\nEssa mensagem é automática, ok? Não é pra responder esse e-mail.' % (instance.user.first_name, instance.name, instance.pages, instance.copy), '*****@*****.**',
def build_survey(request, survey_id): survey = Survey.objects.get(pk=survey_id) name = '' if request.method == 'POST': new_visitor = Visitor.objects.create(survey=survey, user=survey.user) data = Dicty.objects.create(name=new_visitor.pk) print('request.POST: ', request.POST) for key in request.POST: if key != 'csrfmiddlewaretoken': poll = Poll.objects.get(pk=key) if poll.poll_type == 'multi': charchoices = CharChoice.objects.filter( pk__in=request.POST.getlist(key)) new_visitor.choices.add(*charchoices) KeyVal.objects.create(container=data, key=poll.group.name, value=str([ choice.group.name for choice in charchoices ])) new_visitor.collected_data = data new_visitor.save() elif poll.poll_type == 'one': choice = CharChoice.objects.get(pk=request.POST[key]) new_visitor.choices.add(choice) KeyVal.objects.create(container=data, key=poll.group.name, value=choice.group.name) new_visitor.collected_data = data new_visitor.save() else: choice, create = CharChoice.objects.get_or_create( choice_text=request.POST[key], poll=poll, created_by_visitor=True, user=survey.user) new_visitor.choices.add(choice) KeyVal.objects.create(container=data, key=poll.group.name, value=choice) new_visitor.collected_data = data new_visitor.save() for survey_attr in survey.surveyattribute_set.all(): if poll in survey_attr.polls.all(): if survey_attr.attr_type == 'summarize': survey_attr.summarize(int(choice.choice_text)) if survey_attr.attr_type == 'count': survey_attr.count(poll, choice) if poll.poll_type == 'email_now': email = choice.choice_text if poll.poll_type == 'first_name': name = choice.choice_text try: split_body = survey.welcome_letter.body.split('//') body = '' for part in split_body: if part == 'first_name': part = name body += part send_mail( survey.welcome_letter.subject, body, survey.user.preferences['email_settings__email_host_user'], [email], connection=get_connection( host=survey.user.preferences[ 'email_settings__comment_notifications_enabled'], port=survey.user.preferences['email_settings__email_port'], password=survey.user. preferences['email_settings__email_password'], username=survey.user. preferences['email_settings__email_host_user'], use_tls=survey.user. preferences['email_settings__enable_TSL']), fail_silently=False) message = '' if survey.notify: send_mail( 'submit notification', message, survey.user.preferences['email_settings__email_host_user'], [survey.user.email], html_message=new_visitor.print_visitor(), connection=get_connection( host=survey.user.preferences[ 'email_settings__comment_notifications_enabled'], port=survey.user. preferences['email_settings__email_port'], password=survey.user. preferences['email_settings__email_password'], username=survey.user. preferences['email_settings__email_host_user'], use_tls=survey.user. preferences['email_settings__enable_TSL']), fail_silently=False) except: print('email address not valid') return HttpResponseRedirect("/thankyou/") polls = Poll.objects.filter(survey=survey, first_level=True) context = {'survey': survey, 'polls': polls} return render(request, 'polls/index.html', context)
def send_queued_message(queued_message, smtp_connection=None, blacklist=None, log=True): """ Send a queued message, returning a response code as to the action taken. The response codes can be found in ``django_mailer.constants``. The response will be either ``RESULT_SKIPPED`` for a blacklisted email, ``RESULT_FAILED`` for a deferred message or ``RESULT_SENT`` for a successful sent message. To allow optimizations if multiple messages are to be sent, an SMTP connection can be provided and a list of blacklisted email addresses. Otherwise an SMTP connection will be opened to send this message and the email recipient address checked against the ``Blacklist`` table. If the message recipient is blacklisted, the message will be removed from the queue without being sent. Otherwise, the message is attempted to be sent with an SMTP failure resulting in the message being flagged as deferred so it can be tried again later. By default, a log is created as to the action. Either way, the original message is not deleted. """ message = queued_message.message if smtp_connection is None: smtp_connection = get_connection() opened_connection = False if blacklist is None: blacklisted = models.Blacklist.objects.filter(email=message.to_address) else: blacklisted = message.to_address in blacklist log_message = '' if blacklisted: logger.info("Not sending to blacklisted email: %s" % message.to_address.encode("utf-8")) queued_message.delete() result = constants.RESULT_SKIPPED else: try: logger.info("Sending message to %s: %s" % (message.to_address.encode("utf-8"), message.subject.encode("utf-8"))) opened_connection = smtp_connection.open() attached_message = EmailMultiAlternatives( message.subject, message.encoded_message, message.from_address, [message.to_address], connection=smtp_connection) if message.html_message: attached_message.attach_alternative(message.html_message, "text/html") if message.attachment: for attachment in message.attachment.all(): attached_message.attach_file(attachment.filename) attached_message.send() # Normal django-mailer behaviour: #smtp_connection.connection.sendmail(message.from_address, # [message.to_address], # message.encoded_message) queued_message.delete() result = constants.RESULT_SENT except (SocketError, smtplib.SMTPSenderRefused, smtplib.SMTPRecipientsRefused, smtplib.SMTPAuthenticationError), err: queued_message.defer() logger.warning("Message to %s deferred due to failure: %s" % (message.to_address.encode("utf-8"), err)) log_message = unicode(err) result = constants.RESULT_FAILED
def send_all(block_size=500, backend=None): """ Send all non-deferred messages in the queue. A lock file is used to ensure that this process can not be started again while it is already running. The ``block_size`` argument allows for queued messages to be iterated in blocks, allowing new prioritised messages to be inserted during iteration of a large number of queued messages. """ lock = FileLock(LOCK_PATH) logger.debug("Acquiring lock...") try: # lockfile has a bug dealing with a negative LOCK_WAIT_TIMEOUT (which # is the default if it's not provided) systems which use a LinkFileLock # so ensure that it is never a negative number. lock.acquire(settings.LOCK_WAIT_TIMEOUT or 0) #lock.acquire(settings.LOCK_WAIT_TIMEOUT) except AlreadyLocked: logger.debug("Lock already in place. Exiting.") return except LockTimeout: logger.debug("Waiting for the lock timed out. Exiting.") return logger.debug("Lock acquired.") start_time = time.time() sent = deferred = skipped = 0 try: if constants.EMAIL_BACKEND_SUPPORT: connection = get_connection(backend=backend) else: connection = get_connection() blacklist = models.Blacklist.objects.values_list('email', flat=True) connection.open() for message in _message_queue(block_size): result = send_queued_message(message, smtp_connection=connection, blacklist=blacklist) if result == constants.RESULT_SENT: sent += 1 elif result == constants.RESULT_FAILED: deferred += 1 elif result == constants.RESULT_SKIPPED: skipped += 1 connection.close() finally: logger.debug("Releasing lock...") lock.release() logger.debug("Lock released.") logger.debug("") if deferred or skipped: log = logger.warning else: log = logger.info log("%s sent, %s deferred, %s skipped." % (sent, deferred, skipped)) logger.debug("Completed in %.2f seconds." % (time.time() - start_time))
domain = 'cimav.edu.mx' ###################################################################################### # ''' con base de datos ''' ###################################################################################### smtpconfig = Configuration.objects.get(pk=1) messageMailSignup = MessageMail.objects.get(pk=3) my_use_tls = False if smtpconfig.email_use_tls == 1: my_use_tls = True fail_silently = False connection = get_connection(host=smtpconfig.email_host, port=int(smtpconfig.email_port), username=smtpconfig.email_host_user, password=smtpconfig.email_host_password, use_tls=my_use_tls) htmlmessage = messageMailSignup.email_regards + " " + user.username + ",</br> " + messageMailSignup.email_message + "</br> " + messageMailSignup.email_message + "</br> " + "http://mpod.cimav.edu.mx/activate/Nzc=/4oq-9cac01d09e86d5e9d2d4" print htmlmessage send_mail(messageMailSignup.email_subject, htmlmessage, smtpconfig.email_host_user, [user.email], connection=connection) ###################################################################################### # ''' sin base de datos ''' ###################################################################################### my_host = 'smtp.gmail.com' my_port = 587
def get_newsletter_connection(): return get_connection(backend=settings.NEWSLETTER_EMAIL_BACKEND)
def _get_real_backend(): real_backend_path = getattr( settings, 'DJMAIL_REAL_BACKEND', 'django.core.mail.backends.console.EmailBackend') return get_connection(backend=real_backend_path, fail_silently=False)
def get_connection(self, fail_silently=False): from django.core.mail import get_connection if not self.connection: self.connection = get_connection(fail_silently=fail_silently) return self.connection
def solution_list(request, task_id, user_id=None): if (user_id and not request.user.is_trainer and not request.user.is_superuser): return access_denied(request) task = get_object_or_404(Task, pk=task_id) author = get_object_or_404(User, pk=user_id) if user_id else request.user solutions = task.solution_set.filter(author=author).order_by('-id') final_solution = task.final_solution(author) if task.publication_date >= datetime.now() and not request.user.is_trainer: raise Http404 if request.method == "POST": if task.expired() and not request.user.is_trainer: return access_denied(request) solution = Solution(task=task, author=author) formset = SolutionFormSet(request.POST, request.FILES, instance=solution) if formset.is_valid(): solution.save() formset.save() run_all_checker = bool( User.objects.filter(id=user_id, tutorial__tutors__pk=request.user.id) or request.user.is_trainer) solution.check_solution(run_all_checker) if solution.accepted: # Send submission confirmation email t = loader.get_template( 'solutions/submission_confirmation_email.html') c = { 'protocol': request.is_secure() and "https" or "http", 'domain': RequestSite(request).domain, 'site_name': settings.SITE_NAME, 'solution': solution, } if user_id: # in case someone else uploaded the solution, add this to the email c['uploader'] = request.user with tempfile.NamedTemporaryFile(mode='w+') as tmp: tmp.write("Content-Type: text/plain; charset=utf-8\n") tmp.write( "Content-Transfer-Encoding: quoted-printable\n\n") tmp.write(t.render(c)) tmp.seek(0) [signed_mail, __, __, __, __] = execute_arglist([ "openssl", "smime", "-sign", "-signer", settings.CERTIFICATE, "-inkey", settings.PRIVATE_KEY, "-in", tmp.name ], ".", unsafe=True) connection = get_connection() message = ConfirmationMessage(_("%s submission confirmation") % settings.SITE_NAME, signed_mail, None, [solution.author.email], connection=connection) if solution.author.email: message.send() if solution.accepted or get_settings().accept_all_solutions: solution.final = True solution.save() return HttpResponseRedirect( reverse('solution_detail', args=[solution.id])) else: formset = SolutionFormSet() attestations = Attestation.objects.filter( solution__task=task, author__tutored_tutorials=request.user.tutorial) attestationsPublished = attestations[0].published if attestations else False return render( request, "solutions/solution_list.html", { "formset": formset, "task": task, "solutions": solutions, "final_solution": final_solution, "attestationsPublished": attestationsPublished, "author": author, "invisible_attestor": get_settings().invisible_attestor })
def send_messages(messages, backend_type): from django.core.mail import get_connection email_backend = get_connection(backend=backend_type) return email_backend.send_messages(messages)
def handle(self, *args, **options): from applications.delivery.models import Delivery try: deliveryes = Delivery.objects.filter( delivery_test=False, send_test=True, send_general=False, type__in=[ 1, 2, 3, ], ) except Delivery.DoesNotExist: deliveryes = None else: from applications.delivery.models import EmailMiddleDelivery for delivery in deliveryes: # print 'delivery', delivery try: EmailMiddleDelivery.objects.\ get(delivery=delivery, send_test=False, send_general=True, updated_at__lte=delivery.updated_at, ) except: """ Создаем ссылочку на отсылку рассылки """ email_middle_delivery = EmailMiddleDelivery() email_middle_delivery.delivery = delivery email_middle_delivery.delivery_test_send = False email_middle_delivery.delivery_send = True email_middle_delivery.save() """ Закрываем отсылку теста в самой рассылке """ delivery.send_general = True delivery.save() """ Отсылаем тестовое письмо """ from django.utils.html import strip_tags EMAIL_USE_TLS = True EMAIL_HOST = 'smtp.yandex.ru' EMAIL_PORT = 587 EMAIL_HOST_USER = '******' EMAIL_HOST_PASSWORD = '' from django.core.mail import get_connection backend = get_connection( backend='django.core.mail.backends.smtp.EmailBackend', host=EMAIL_HOST, port=EMAIL_PORT, username=EMAIL_HOST_USER, password=EMAIL_HOST_PASSWORD, use_tls=EMAIL_USE_TLS, fail_silently=False, ) from django.core.mail import EmailMultiAlternatives from proj.settings import Email_MANAGER from applications.authModel.models import Email """ Создаем указатели на E-Mail адреса рассылки """ try: emails = Email.objects.filter(bad_email=False, ) except Email.DoesNotExist: emails = None """ Здесь нужно помудрить с коммитом """ from applications.delivery.models import EmailForDelivery from applications.delivery.utils import parsing i = 0 time = 0 for real_email in emails: i += 1 # if i < 125: # continue email = EmailForDelivery.objects.create( delivery=email_middle_delivery, email=real_email, ) """ Отсылка """ msg = EmailMultiAlternatives( subject=delivery.subject, body=strip_tags( parsing( value=delivery.html, key=email.key, ), ), from_email='*****@*****.**', to=[ real_email.email, ], connection=backend, ) msg.attach_alternative( content=parsing( value=delivery.html, key=email.key, ), mimetype="text/html", ) msg.content_subtype = "html" try: msg.send(fail_silently=False, ) except Exception as e: msg = EmailMultiAlternatives( subject='Error for subject: %s' % delivery.subject, body= 'Error: %s - E-Mail: %s - real_email.pk: %d' % ( e, real_email.email, real_email.pk, ), from_email='*****@*****.**', to=[ '*****@*****.**', ], connection=backend, ) msg.send(fail_silently=True, ) else: print 'i: ', i, 'Pk: ', real_email.pk, ' - ', real_email.email from random import randrange time1 = randrange( 6, 12, ) time2 = randrange( 6, 12, ) time += time1 + time2 print 'Time1: ', time1, ' Time2: ', time2, ' Time all: ', time1 + time2, ' average time: ', time / i from time import sleep sleep(time1, ) print 'Next' sleep(time2, )
def send_product_alerts(product): # noqa C901 too complex """ Check for notifications for this product and send email to users if the product is back in stock. Add a little 'hurry' note if the amount of in-stock items is less then the number of notifications. """ stockrecords = product.stockrecords.all() num_stockrecords = len(stockrecords) if not num_stockrecords: return logger.info("Sending alerts for '%s'", product) alerts = ProductAlert.objects.filter( product_id__in=(product.id, product.parent_id), status=ProductAlert.ACTIVE, ) # Determine 'hurry mode' if num_stockrecords == 1: num_in_stock = stockrecords[0].num_in_stock else: result = stockrecords.aggregate(max_in_stock=Max('num_in_stock')) num_in_stock = result['max_in_stock'] # hurry_mode is false if num_in_stock is None hurry_mode = num_in_stock is not None and alerts.count() > num_in_stock # For backwards compability, we check if the old (non-communication-event) # templates exist, and use them if they do. # This will be removed in Oscar 2.0 try: email_subject_tpl = loader.get_template('customer/alerts/emails/' 'alert_subject.txt') email_body_tpl = loader.get_template('customer/alerts/emails/' 'alert_body.txt') use_deprecated_templates = True warnings.warn( "Product alert notifications now use the CommunicationEvent. " "Move '{}' to '{}', and '{}' to '{}'".format( 'customer/alerts/emails/alert_subject.txt', 'customer/emails/commtype_product_alert_subject.txt', 'customer/alerts/emails/alert_body.txt', 'customer/emails/commtype_product_alert_body.txt', ), category=RemovedInOscar20Warning, stacklevel=2) except TemplateDoesNotExist: code = 'PRODUCT_ALERT' try: event_type = CommunicationEventType.objects.get(code=code) except CommunicationEventType.DoesNotExist: event_type = CommunicationEventType.objects.model(code=code) use_deprecated_templates = False messages_to_send = [] user_messages_to_send = [] num_notifications = 0 selector = Selector() for alert in alerts: # Check if the product is available to this user strategy = selector.strategy(user=alert.user) data = strategy.fetch_for_product(product) if not data.availability.is_available_to_buy: continue ctx = { 'alert': alert, 'site': Site.objects.get_current(), 'hurry': hurry_mode, } if alert.user: # Send a site notification num_notifications += 1 subj_tpl = loader.get_template( 'customer/alerts/message_subject.html') message_tpl = loader.get_template('customer/alerts/message.html') services.notify_user(alert.user, subj_tpl.render(ctx).strip(), body=message_tpl.render(ctx).strip()) # Build message and add to list if use_deprecated_templates: messages = { 'subject': email_subject_tpl.render(ctx).strip(), 'body': email_body_tpl.render(ctx), 'html': '', 'sms': '', } else: messages = event_type.get_messages(ctx) if messages and messages['body']: if alert.user: user_messages_to_send.append((alert.user, messages)) else: messages_to_send.append((alert.get_email_address(), messages)) alert.close() # Send all messages using one SMTP connection to avoid opening lots of them if messages_to_send or user_messages_to_send: connection = mail.get_connection() connection.open() disp = Dispatcher(mail_connection=connection) for message in messages_to_send: disp.dispatch_direct_messages(*message) for message in user_messages_to_send: disp.dispatch_user_messages(*message) connection.close() logger.info("Sent %d notifications and %d messages", num_notifications, len(messages_to_send) + len(user_messages_to_send))
def send_all(): """ Send all eligible messages in the queue. """ # The actual backend to use for sending, defaulting to the Django default. # To make testing easier this is not stored at module level. EMAIL_BACKEND = getattr(settings, "MAILER_EMAIL_BACKEND", "django.core.mail.backends.smtp.EmailBackend") acquired, lock = acquire_lock() if not acquired: return start_time = time.time() deferred = 0 sent = 0 try: for message in prioritize(): try: print('MSG', message.email.host, message.email.port, message.email.username) if message.email.connection: connection = EmailBackend(host=message.email.host, port=message.email.port, username=message.email.username, password=message.email.password, use_tls=message.email.use_tls, use_ssl=message.email.use_ssl) else: connection = get_connection(backend=EMAIL_BACKEND, ) logging.info("sending message '{0}' to {1}".format( message.subject, ", ".join([str(email) for email in message.to_addresses]))) email = message.email if email is not None: email.connection = connection if not hasattr(email, 'reply_to'): # Compatability fix for EmailMessage objects # pickled when running < Django 1.8 and then # unpickled under Django 1.8 email.reply_to = [] ensure_message_id(email) print('YYYY') email.send() print('XXXXs') # connection can't be stored in the MessageLog email.connection = None message.email = email # For the sake of MessageLog MessageLog.objects.log(message, RESULT_SUCCESS) sent += 1 else: logging.warning( "message discarded due to failure in converting from DB. Added on '%s' with priority '%s'" % (message.when_added, message.priority)) # noqa message.delete() except (socket_error, smtplib.SMTPSenderRefused, smtplib.SMTPRecipientsRefused, smtplib.SMTPDataError, smtplib.SMTPAuthenticationError) as err: message.defer() traceback.print_exc() logging.info("message deferred due to failure: %s" % err) MessageLog.objects.log(message, RESULT_FAILURE, log_message=str(err)) deferred += 1 # Get new connection, it case the connection itself has an error. # Check if we reached the limits for the current run if _limits_reached(sent, deferred): break _throttle_emails() finally: release_lock(lock) logging.info("") logging.info("%s sent; %s deferred;" % (sent, deferred)) logging.info("done in %.2f seconds" % (time.time() - start_time))
def get_mail_connection(**kwargs): return get_connection( backend=settings.EMAIL_BACKEND, **kwargs )
def send_HTML_email(subject, recipient, html_content, text_content=None, cc=None, email_from=settings.DEFAULT_FROM_EMAIL, file_attachments=None, bcc=None, smtp_exception_skip_list=None): from corehq.util.python_compatibility import soft_assert_type_text if isinstance(recipient, six.string_types): soft_assert_type_text(recipient) recipient = list(recipient) if not isinstance( recipient, six.string_types) else [recipient] if not isinstance(html_content, six.text_type): html_content = html_content.decode('utf-8') if not text_content: text_content = getattr(settings, 'NO_HTML_EMAIL_MESSAGE', NO_HTML_EMAIL_MESSAGE) elif not isinstance(text_content, six.text_type): text_content = text_content.decode('utf-8') from_header = {'From': email_from} # From-header connection = get_connection() msg = EmailMultiAlternatives(subject, text_content, email_from, recipient, headers=from_header, connection=connection, cc=cc, bcc=bcc) for file in (file_attachments or []): if file: msg.attach(file["title"], file["file_obj"].getvalue(), file["mimetype"]) msg.attach_alternative(html_content, "text/html") try: msg.send() except SMTPSenderRefused as e: if smtp_exception_skip_list and e.smtp_code in smtp_exception_skip_list: raise e else: error_subject = _('ERROR: Could not send "%(subject)s"') % { 'subject': subject, } if e.smtp_code in LARGE_FILE_SIZE_ERROR_CODES: error_text = _('Could not send email: file size is too large.') else: error_text = e.smtp_error error_text = '%s\n\n%s' % ( error_text, _('Please contact %(support_email)s for assistance.') % { 'support_email': settings.SUPPORT_EMAIL, }, ) error_msg = EmailMultiAlternatives( error_subject, error_text, email_from, recipient, headers=from_header, connection=connection, cc=cc, bcc=bcc, ) error_msg.send()
def test_bare_setting(self): """ESP settings are also usually allowed at root of settings file""" backend = get_connection() self.assertEqual(backend.sample_setting, 'setting_from_bare_settings')
def _send_email( campaign_key: str, to: List[Dict[str, str]], subject: str, headers: Dict, txt_body: str = "", html_body: str = "", ) -> None: """ Sends built email message asynchronously. """ messages: List = [] records: List = [] with transaction.atomic(): for dest in to: record, _ = MessagingRecord.objects.get_or_create( raw_email=dest["raw_email"], campaign_key=campaign_key) # Lock object (database-level) while the message is sent record = MessagingRecord.objects.select_for_update().get( pk=record.pk) # If an email for this campaign was already sent to this user, skip recipient if record.sent_at: record.save() # release DB lock continue records.append(record) email_message = mail.EmailMultiAlternatives( subject=subject, body=txt_body, to=[dest["recipient"]], headers=headers, ) email_message.attach_alternative(html_body, "text/html") messages.append(email_message) connection = None try: connection = mail.get_connection() connection.open() connection.send_messages(messages) for record in records: record.sent_at = timezone.now() record.save() except Exception as e: # Handle exceptions gracefully to avoid breaking the entire task for all teams # but make sure they're tracked on Sentry. capture_exception(e) finally: # ensure that connection has been closed try: connection.close() # type: ignore except Exception: pass
def get_connection(self): return get_connection('bandit.backends.smtp.LogOnlySMTPBackend')
def _flush(self, **kwargs): if len(self.messages) == 0: return kwargs = dict({ 'request': None, 'form': None, 'fail_silently': False, }, **kwargs) request = kwargs.pop('request', None) form = kwargs.pop('form', None) self.connection = kwargs.get('connection', self.connection) self.connection = self.connection or mail.get_connection(**kwargs) try: # raise SMTPDataError(code=123, msg='Test error') if hasattr(self.ioc, 'before_sending'): self.ioc.before_sending() result = self.connection.send_messages(self.messages) if hasattr(self.ioc, 'success'): self.ioc.success() self.messages = [] return result except (SMTPDataError, SMTPServerDisconnected, SMTPRecipientsRefused, SMTPSenderRefused, gaierror, ConnectionError) as e: if isinstance(e, SMTPDataError): title = e.smtp_code trans_msg = 'Error "%(err_type)s" "%(code)s" "%(msg)s" while sending email.' trans_params = { 'err_type': e.__class__.__name__, 'code': e.smtp_code, 'msg': e.smtp_error, } if isinstance(e, SMTPServerDisconnected): self.connection = mail.get_connection(**kwargs) title = 'SMTP server disconnected' trans_msg = 'Error "%(err_type)s" "%(msg)s" while sending email.' trans_params = { 'err_type': e.__class__.__name__, 'code': 1, 'msg': str(e), } else: title = e.errno trans_msg = 'Error "%(err_type)s" "%(code)s" "%(msg)s" while the transmission attempt.' trans_params = { 'err_type': e.__class__.__name__, 'code': e.errno, 'msg': e.strerror, } msg = _(trans_msg) % trans_params raise_error = self.ioc.error( **trans_params) if hasattr(self.ioc, 'error') else True if form is not None: form.add_error(None, msg) elif request is not None: if is_ajax(request): raise ImmediateJsonResponse({ 'view': 'alert_error', 'title': title, 'message': msg }) else: messages.error(request, msg) elif raise_error: raise e
def sendmail(request): current_user = request.user users = User.objects.all() customer = Customer.objects.all() campaign = Campaign.objects.all() email = Email.objects.all() campaigns = Campaign.objects.filter(my_customer=current_user.id) campmaildata = Campaign.objects.filter(camp_emails=current_user.id) emails = Email.objects.filter(my_customer=current_user.id) print(campmaildata) pi = Customer.objects.get(pk=current_user.id) if request.method == "POST" and request.FILES['file']: job = request.POST.get('job') message = request.POST.get('message') subject = "" file_names = "" getid = "" for e in Campaign.objects.filter(id=job): subject = e.email_subject getid = e.camp_emails.id print(getid) for f in Email.objects.filter(id=getid): file_names = f.upload_file from_email = settings.EMAIL_HOST_USER file = request.FILES['file'] file_name = default_storage.save(file.name, file) df_file = pd.read_csv(file_names) # print(df_file) connection = mail.get_connection() connection.open() df = pd.DataFrame(df_file) list = df['Email'].tolist() email = mail.EmailMessage(subject, message, from_email, bcc=list, connection=connection) file = default_storage.open(file_name) file_url = default_storage.url(file_name) email.attach(file_url, file.read()) connection.send_messages([email]) messages.success(request, "Email sent Successfully") connection.close() return redirect('/customer') context = { 'campaign': campaign, 'email': email, 'customer': customer, 'current_user': current_user, 'campaigns': campaigns, 'emails': emails, } return render(request, 'sendmail.html', context)
def test_anymail_setting(self): """ESP settings usually come from ANYMAIL settings dict""" backend = get_connection() self.assertEqual(backend.sample_setting, 'setting_from_anymail_settings')
def connection(self): return get_connection(backend=self.email_backend, fail_silently=True)
def send_mail(subject, email_body, user_to=None, email_to=None, email_from=None, reply_to=None, email_type_preference_check=None): """Sends email with a lot of defaults. The function will check if user's email is valid based on bounce info. The function will also check email preferences of destinataries of the email. Parameters user_to and email_to are mutually exclusive, if one is set, other should be None. Args: subject (str): subject of the email. email_body (str): body of the email. user_to (Union[User, List[User]]): a User object or a list of User objects to send the email to. If user_to is set, email_to should be None. email_to (Union[str, List[str]]): a string representing an email address or a list of strings representing email addresses who to send the email to. If email_to is set, user_to should be None. email_from (str): email string that shows up as sender. The default value is DEFAULT_FROM_EMAIL in config. reply_to (str): cemail string that will be added as a "Reply-To" header to all mails being sent. email_type_preference_check (str): name of EmailPreferenceType that users should have enabled for the email to be sent. If set to None, no checks will be carried out. Returns: (bool): True if all emails were sent successfully, False otherwise. """ assert bool(user_to) != bool(email_to), "One of parameters user_to and email_to should be set, but not both" if email_from is None: email_from = settings.DEFAULT_FROM_EMAIL if user_to: user_to = _ensure_list(user_to) email_to = [] for user in user_to: # Check that user has preference enabled for that type of email email_type_enabled = user.profile.email_type_enabled(email_type_preference_check) \ if email_type_preference_check is not None else True # Check if user's email is valid for delivery and add the correct email address to the list of email_to if user.profile.email_is_valid() and email_type_enabled: email_to.append(user.profile.get_email_for_delivery()) # If all users have invalid emails or failed preference check, send no emails if len(email_to) == 0: return False if email_to: email_to = _ensure_list(email_to) if settings.ALLOWED_EMAILS: # for testing purposes, so we don't accidentally send emails to users email_to = [email for email in email_to if email in settings.ALLOWED_EMAILS] try: emails = tuple(((settings.EMAIL_SUBJECT_PREFIX + subject, email_body, email_from, [email]) for email in email_to)) # Replicating send_mass_mail functionality and adding reply-to header if requires connection = get_connection(username=None, password=None, fail_silently=False) headers = None if reply_to: headers = {'Reply-To': reply_to} messages = [EmailMessage(subject, message, sender, recipient, headers=headers) for subject, message, sender, recipient in emails] connection.send_messages(messages) return True except Exception: return False
def refuse(self, *args, **kwargs): # Send notification. connection = mail.get_connection() emails = [self.email_refuse] connection.send_messages(emails)
def _send_course_email(entry_id, email_id, to_list, global_email_context, subtask_status): """ Performs the email sending task. Sends an email to a list of recipients. Inputs are: * `entry_id`: id of the InstructorTask object to which progress should be recorded. * `email_id`: id of the CourseEmail model that is to be emailed. * `to_list`: list of recipients. Each is represented as a dict with the following keys: - 'profile__name': full name of User. - 'email': email address of User. - 'pk': primary key of User model. * `global_email_context`: dict containing values that are unique for this email but the same for all recipients of this email. This dict is to be used to fill in slots in email template. It does not include 'name' and 'email', which will be provided by the to_list. * `subtask_status` : object of class SubtaskStatus representing current status. Sends to all addresses contained in to_list that are not also in the Optout table. Emails are sent multi-part, in both plain text and html. Returns a tuple of two values: * First value is a SubtaskStatus object which represents current progress at the end of this call. * Second value is an exception returned by the innards of the method, indicating a fatal error. In this case, the number of recipients that were not sent have already been added to the 'failed' count above. """ # Get information from current task's request: parent_task_id = InstructorTask.objects.get(pk=entry_id).task_id task_id = subtask_status.task_id total_recipients = len(to_list) recipient_num = 0 total_recipients_successful = 0 total_recipients_failed = 0 recipients_info = Counter() log.info( "BulkEmail ==> Task: %s, SubTask: %s, EmailId: %s, TotalRecipients: %s", parent_task_id, task_id, email_id, total_recipients) try: course_email = CourseEmail.objects.get(id=email_id) except CourseEmail.DoesNotExist as exc: log.exception( "BulkEmail ==> Task: %s, SubTask: %s, EmailId: %s, Could not find email to send.", parent_task_id, task_id, email_id) raise # Exclude optouts (if not a retry): # Note that we don't have to do the optout logic at all if this is a retry, # because we have presumably already performed the optout logic on the first # attempt. Anyone on the to_list on a retry has already passed the filter # that existed at that time, and we don't need to keep checking for changes # in the Optout list. if subtask_status.get_retry_count() == 0: to_list, num_optout = _filter_optouts_from_recipients( to_list, course_email.course_id) subtask_status.increment(skipped=num_optout) course_title = global_email_context['course_title'] subject = "[" + course_title + "] " + course_email.subject # use the email from address in the CourseEmail, if it is present, otherwise compute it from_addr = course_email.from_addr if course_email.from_addr else \ _get_source_address(course_email.course_id, course_title) # use the CourseEmailTemplate that was associated with the CourseEmail course_email_template = course_email.get_template() try: connection = get_connection() connection.open() # Define context values to use in all course emails: email_context = {'name': '', 'email': ''} email_context.update(global_email_context) while to_list: # Update context with user-specific values from the user at the end of the list. # At the end of processing this user, they will be popped off of the to_list. # That way, the to_list will always contain the recipients remaining to be emailed. # This is convenient for retries, which will need to send to those who haven't # yet been emailed, but not send to those who have already been sent to. recipient_num += 1 current_recipient = to_list[-1] email = current_recipient['email'] email_context['email'] = email email_context['name'] = current_recipient['profile__name'] email_context['user_id'] = current_recipient['pk'] email_context['course_id'] = course_email.course_id # Construct message content using templates and context: plaintext_msg = course_email_template.render_plaintext( course_email.text_message, email_context) html_msg = course_email_template.render_htmltext( course_email.html_message, email_context) # Create email: email_msg = EmailMultiAlternatives(subject, plaintext_msg, from_addr, [email], connection=connection) email_msg.attach_alternative(html_msg, 'text/html') # Throttle if we have gotten the rate limiter. This is not very high-tech, # but if a task has been retried for rate-limiting reasons, then we sleep # for a period of time between all emails within this task. Choice of # the value depends on the number of workers that might be sending email in # parallel, and what the SES throttle rate is. if subtask_status.retried_nomax > 0: sleep(settings.BULK_EMAIL_RETRY_DELAY_BETWEEN_SENDS) try: log.info( "BulkEmail ==> Task: %s, SubTask: %s, EmailId: %s, Recipient num: %s/%s, \ Recipient name: %s, Email address: %s", parent_task_id, task_id, email_id, recipient_num, total_recipients, current_recipient['profile__name'], email) with dog_stats_api.timer( 'course_email.single_send.time.overall', tags=[_statsd_tag(course_title)]): connection.send_messages([email_msg]) except SMTPDataError as exc: # According to SMTP spec, we'll retry error codes in the 4xx range. 5xx range indicates hard failure. total_recipients_failed += 1 log.error( "BulkEmail ==> Status: Failed(SMTPDataError), Task: %s, SubTask: %s, EmailId: %s, \ Recipient num: %s/%s, Email address: %s", parent_task_id, task_id, email_id, recipient_num, total_recipients, email) if exc.smtp_code >= 400 and exc.smtp_code < 500: # This will cause the outer handler to catch the exception and retry the entire task. raise exc else: # This will fall through and not retry the message. log.warning( 'BulkEmail ==> Task: %s, SubTask: %s, EmailId: %s, Recipient num: %s/%s, \ Email not delivered to %s due to error %s', parent_task_id, task_id, email_id, recipient_num, total_recipients, email, exc.smtp_error) dog_stats_api.increment('course_email.error', tags=[_statsd_tag(course_title)]) subtask_status.increment(failed=1) except SINGLE_EMAIL_FAILURE_ERRORS as exc: # This will fall through and not retry the message. total_recipients_failed += 1 log.error( "BulkEmail ==> Status: Failed(SINGLE_EMAIL_FAILURE_ERRORS), Task: %s, SubTask: %s, \ EmailId: %s, Recipient num: %s/%s, Email address: %s, Exception: %s", parent_task_id, task_id, email_id, recipient_num, total_recipients, email, exc) dog_stats_api.increment('course_email.error', tags=[_statsd_tag(course_title)]) subtask_status.increment(failed=1) else: total_recipients_successful += 1 log.info( "BulkEmail ==> Status: Success, Task: %s, SubTask: %s, EmailId: %s, \ Recipient num: %s/%s, Email address: %s,", parent_task_id, task_id, email_id, recipient_num, total_recipients, email) dog_stats_api.increment('course_email.sent', tags=[_statsd_tag(course_title)]) if settings.BULK_EMAIL_LOG_SENT_EMAILS: log.info('Email with id %s sent to %s', email_id, email) else: log.debug('Email with id %s sent to %s', email_id, email) subtask_status.increment(succeeded=1) # Pop the user that was emailed off the end of the list only once they have # successfully been processed. (That way, if there were a failure that # needed to be retried, the user is still on the list.) recipients_info[email] += 1 to_list.pop() log.info( "BulkEmail ==> Task: %s, SubTask: %s, EmailId: %s, Total Successful Recipients: %s/%s, \ Failed Recipients: %s/%s", parent_task_id, task_id, email_id, total_recipients_successful, total_recipients, total_recipients_failed, total_recipients) duplicate_recipients = [ "{0} ({1})".format(email, repetition) for email, repetition in recipients_info.most_common() if repetition > 1 ] if duplicate_recipients: log.info( "BulkEmail ==> Task: %s, SubTask: %s, EmailId: %s, Total Duplicate Recipients [%s]: [%s]", parent_task_id, task_id, email_id, len(duplicate_recipients), ', '.join(duplicate_recipients)) except INFINITE_RETRY_ERRORS as exc: dog_stats_api.increment('course_email.infinite_retry', tags=[_statsd_tag(course_title)]) # Increment the "retried_nomax" counter, update other counters with progress to date, # and set the state to RETRY: subtask_status.increment(retried_nomax=1, state=RETRY) return _submit_for_retry(entry_id, email_id, to_list, global_email_context, exc, subtask_status, skip_retry_max=True) except LIMITED_RETRY_ERRORS as exc: # Errors caught here cause the email to be retried. The entire task is actually retried # without popping the current recipient off of the existing list. # Errors caught are those that indicate a temporary condition that might succeed on retry. dog_stats_api.increment('course_email.limited_retry', tags=[_statsd_tag(course_title)]) # Increment the "retried_withmax" counter, update other counters with progress to date, # and set the state to RETRY: subtask_status.increment(retried_withmax=1, state=RETRY) return _submit_for_retry(entry_id, email_id, to_list, global_email_context, exc, subtask_status, skip_retry_max=False) except BULK_EMAIL_FAILURE_ERRORS as exc: dog_stats_api.increment('course_email.error', tags=[_statsd_tag(course_title)]) num_pending = len(to_list) log.exception( 'Task %s: email with id %d caused send_course_email task to fail with "fatal" exception. %d emails unsent.', task_id, email_id, num_pending) # Update counters with progress to date, counting unsent emails as failures, # and set the state to FAILURE: subtask_status.increment(failed=num_pending, state=FAILURE) return subtask_status, exc except Exception as exc: # Errors caught here cause the email to be retried. The entire task is actually retried # without popping the current recipient off of the existing list. # These are unexpected errors. Since they might be due to a temporary condition that might # succeed on retry, we give them a retry. dog_stats_api.increment('course_email.limited_retry', tags=[_statsd_tag(course_title)]) log.exception( 'Task %s: email with id %d caused send_course_email task to fail with unexpected exception. Generating retry.', task_id, email_id) # Increment the "retried_withmax" counter, update other counters with progress to date, # and set the state to RETRY: subtask_status.increment(retried_withmax=1, state=RETRY) return _submit_for_retry(entry_id, email_id, to_list, global_email_context, exc, subtask_status, skip_retry_max=False) else: # All went well. Update counters with progress to date, # and set the state to SUCCESS: subtask_status.increment(state=SUCCESS) # Successful completion is marked by an exception value of None. return subtask_status, None finally: # Clean up at the end. connection.close()