def send_email(push, commit, request): mailer = get_mailer(request) settings = request.registry.settings commitwarning = None repository = push['repository']['name'] pusher_email = push['pusher'].get('email', '') if pusher_email != commit['author']['email']: # Pusher != Committer, do stuff commitwarning = 'Code author and pusher do not match!' short_commit_msg = commit['message'].split('\n')[0][:60] reply_to = '%s <%s>' % (commit['author']['name'], commit['author']['email']) diff = requests.get(commit['url'] + '.diff').content files = ['A %s' % f for f in commit['added']] files.extend('M %s' % f for f in commit['modified']) files.extend('D %s' % f for f in commit['removed']) data = { 'push': push, 'commit': commit, 'files': '\n'.join(files), 'diff': diff, 'commitwarning': commitwarning, 'pusher_email': pusher_email } recipients = ["%s" % settings['recipient_email']] if repository in ADDED_RECIPIENTS: recipients.extend(ADDED_RECIPIENTS[repository]) msg = Message(subject='%s/%s: %s' % (repository, push['ref'].split('/')[-1], short_commit_msg), sender="%s <%s>" % (commit['author']['name'], settings['sender_email']), recipients=recipients, body=TMPLS['commit_email.pt'](**data), extra_headers={'Reply-To': reply_to}) mailer.send(msg) if pusher_email != commit['author']['email']: # Warn the committer - he may not be aware of the commit msg = Message( subject='%s/%s: %s' % (repository, push['ref'].split('/')[-1], short_commit_msg), sender= "Zope Foundation contributor committee <*****@*****.**>", recipients=[commit['author']['email']], body=TMPLS['committer_warning.pt'](**data), ) mailer.send(msg)
def mail_to_cvs(payload, mailer): # safeguard against github getting confused and sending us the entire # history if len(payload['commits']) > 40: return for commit in payload['commits']: commit_data = get_info_from_commit(commit) data = { 'push': payload, 'commit': commit, 'files': '\n'.join(commit_data['files']), 'diff': commit_data['diff'], } repo_name = payload['repository']['name'] branch = payload['ref'].split('/')[-1] commit_msg = commit_data['short_commit_msg'] msg = Message( subject=f'{repo_name}/{branch}: {commit_msg}', sender=f'{commit["committer"]["name"]} <*****@*****.**>', recipients=['*****@*****.**'], body=templates['commit_email.pt'](**data), extra_headers={'Reply-To': commit_data['reply_to']}, ) mailer.send_immediately(msg, fail_silently=False)
def merge_to_umail(ldap_conn, mailer, umail, other): umail = umail.lower() other_user = User.fetch_by(username=other) if not other_user: print('Invalid user: {}'.format(other)) return name = helper.fetch_name(ldap_conn, umail) if not name: print('Invalid umail: {}'.format(umail)) return to = '{} <{}>'.format(name, other) umail_user = User.fetch_by(username=umail) if umail_user: print('Merging {} with {}'.format(other_user, umail_user)) helper.merge_users(umail_user, other_user) subject = 'submit.cs accounts merged' body = ('Your submit.cs account {old} has been merged with the account' ' {umail}. You will need to use {umail} and its associated ' 'password to login.\n\nIf you need to reset your password ' 'visit: https://submit.cs.ucsb.edu/password_reset'.format( old=other, umail=umail)) else: print('Changing {} to {}'.format(other_user, umail)) subject = 'submit.cs account username changed' body = ('Your submit.cs account name has been changed to {umail}. ' 'You will need to use this email to login on the submission ' 'system.'.format(umail=umail)) other_user.name = name other_user.username = umail if mailer: body += '\n\nThank you,\nBryce Boe' message = Message(subject=subject, body=body, recipients=[to]) mailer.send_immediately(message)
def render_mail(request, recipients, template, data, subject, **kw): body = render(template_path(template), data, request) return Message(recipients=recipients, subject=subject, html=body, body=html2text(body), **kw)
def mail_signature_confirmation(self, member_id, request): """ Sends an email to the member in order to confirm that the signed contract was received by the C3S. Args: member_id (int): The ID of the member to which the confirmation email is sent. """ # TODO: # - Email functionality should be injected to be testable! # - Email functionality is an external service which belongs to # cross-cutting concerns. # - Emailing service should be independent of the presentation layer, # i.e. independent from pyramid which makes it hard to use # pyramid_mailer. # - Resolve request dependency. # - Remove dependency to pyramid_mail and move to separate service. member = self.member_repository.get_member_by_id(member_id) # pylint: disable=too-many-function-args email_subject, email_body = make_signature_confirmation_email(member) message = Message( subject=email_subject, sender='*****@*****.**', recipients=[member.email], body=email_body ) # pylint: disable=too-many-function-args send_message(request, message) member.signature_confirmed = True member.signature_confirmed_date = self.datetime.now()
def confirmation_page(request): form = RequestForm() session = request.session csrf_token = session.get_csrf_token() if 'uc' not in request.session: request.session.flash('Please login to place request') return HTTPFound(location=request.route_url('login')) submitter_email = request.session['uniqueName'] + '@' + \ request.registry.settings['EMAIL_DOMAIN'] name = request.session['firstName'] + ' ' + request.session['lastName'] sender = request.registry.settings['mail.username'] message = Message(subject="Relay account setup", sender=sender, recipients=[sender, submitter_email]) message.body = make_msg_text(name, submitter_email, request.session['requestDetails'], form) message.html = make_msg_html(name, submitter_email, request.session['requestDetails'], form) mailer = get_mailer(request) mailer.send_immediately(message, fail_silently=False) return { 'csrf_token': csrf_token, 'name': name, 'form': form, 'requestDetails': request.session['requestDetails'] }
def accountant_mail(appstruct): """ this function returns a message object for the mailer it consists of a mail body and an attachment attached to it """ unencrypted = make_mail_body(appstruct) #print("accountant_mail: mail body: \n%s") % unencrypted #print("accountant_mail: type of mail body: %s") % type(unencrypted) encrypted = encrypt_with_gnupg(unencrypted) #print("accountant_mail: mail body (enc'd): \n%s") % encrypted #print("accountant_mail: type of mail body (enc'd): %s") % type(encrypted) message_recipient = appstruct['message_recipient'] message = Message(subject="[C3S] Yes! a new member", sender="*****@*****.**", recipients=[message_recipient], body=encrypted) #print("accountant_mail: csv_payload: \n%s") % generate_csv(appstruct) #print( # "accountant_mail: type of csv_payload: \n%s" #) % type(generate_csv(appstruct)) csv_payload_encd = encrypt_with_gnupg(generate_csv(appstruct)) #print("accountant_mail: csv_payload_encd: \n%s") % csv_payload_encd #print( # "accountant_mail: type of csv_payload_encd: \n%s" #) % type(csv_payload_encd) attachment = Attachment("C3S-SCE-AFM.csv.gpg", "application/gpg-encryption", csv_payload_encd) message.attach(attachment) return message
def test_to_message_multipart(self): from pyramid_mailer.message import Message, Attachment response = Message(recipients=['To'], sender='From', subject='Subject', body='Body', html='Html') attachment_type = 'text/html' this = os.path.abspath(__file__) attachment = Attachment(filename=this, content_type=attachment_type, data='data'.encode('ascii'), disposition='disposition') response.attach(attachment) message = response.to_message() self.assertEqual(message['Content-Type'], 'multipart/mixed') payload = message.get_payload() self.assertEqual(len(payload), 2) self.assertEqual(payload[0]['Content-Type'], 'multipart/alternative') self.assertTrue(payload[1]['Content-Type'].startswith(attachment_type)) alt_payload = payload[0].get_payload() self.assertTrue( alt_payload[0]['Content-Type'].startswith('text/plain')) self.assertTrue(alt_payload[1]['Content-Type'].startswith('text/html'))
def send(self, message_data=None): """Send the message with the given subject body can be sent as part of send() or it can be set to the object as msg.body = "xxx" """ self.body = self._get_message_body(self.message_file, message_data) msg = MIMEMultipart('related') msg['Subject'] = self.subject msg['From'] = self.from_addr msg['To'] = self.to plain_text = MIMEText(self.body, 'plain', _charset="UTF-8") msg.attach(plain_text) LOG.debug('msg: ' + repr(msg)) app_settings = bootstrap(path.join(path.dirname(path.dirname(path.dirname(__file__))), "development.ini"))['registry'].settings mailer = pyramid_mailer.mailer.Mailer.from_settings(app_settings) message = Message(subject=msg['Subject'], recipients=[msg['To']], body=self.body) mailer.send_immediately(message, fail_silently=False) return MSG_STATUS['sent']
def send_report(task, report, status, target, registry=None): # pylint: disable=unused-argument """Send mail report to given target""" if not IMailNotification.providedBy(target): return scheduler = get_parent(task, IScheduler) try: mailer_name = scheduler.report_mailer except (TypeError, AttributeError, ComponentLookupError): return mailer = queryUtility(IMailer, mailer_name) if mailer is not None: report_source = scheduler.report_source if status == TASK_STATUS_ERROR: subject = "[SCHEDULER !ERROR!] {}".format(task.name) elif status == TASK_STATUS_WARNING: subject = "[SCHEDULER WARNING] {}".format(task.name) else: subject = "[scheduler] {}".format(task.name) for email in target.target_email or (): message = Message(subject=subject, sender=report_source, recipients=(email, ), body=report.getvalue()) mailer.send(message)
def render_to_message(self): from ..lib.frontend_urls import FrontendUrls email_text_part = self.render_to_email_text_part() or None email_html_part = self.render_to_email_html_part() if not email_text_part and not email_html_part: return '' frontendUrls = FrontendUrls(self.first_matching_subscription.discussion) headers = {} msg = email.mime.Multipart.MIMEMultipart('alternative') headers['Precedence'] = 'list' headers['List-ID'] = self.first_matching_subscription.discussion.uri() headers['Date'] = email.Utils.formatdate() headers['Message-ID'] = "<"+self.event_source_object().message_id+">" if self.event_source_object().parent: headers['In-Reply-To'] = "<"+self.event_source_object().parent.message_id+">" #Archived-At: A direct link to the archived form of an individual email message. headers['List-Subscribe'] = frontendUrls.getUserNotificationSubscriptionsConfigurationUrl() headers['List-Unsubscribe'] = frontendUrls.getUserNotificationSubscriptionsConfigurationUrl() sender = u"%s <%s>" % ( self.event_source_object().creator.name, self.get_from_email_address()) recipient = self.get_to_email_address() message = Message( subject=self.get_notification_subject(), sender=sender, recipients=[recipient], extra_headers=headers, body=email_text_part, html=email_html_part) return message
def send_invites_success(self, appstruct): settings = self.request.registry.settings mailer = Mailer( host=settings['mail.host'], port=settings['mail.port'], username=settings['bimt.referrals_mail_username'], password=settings['bimt.referrals_mail_password'], tls=True, default_sender=settings['bimt.referrals_mail_sender'], ) emails = appstruct['emails'].splitlines() for email in emails: mailer.send( Message( subject=u'Your friend, {}, gave you exclusive access to {}' .format( # noqa self.request.user.fullname, settings['bimt.app_title']), recipients=[ email, ], html=render('pyramid_bimt:templates/referral_email.pt', {'request': self.request}), ), ) self.request.registry.notify( ReferralEmailSent(self.request, self.request.user, 'Referral email sent to: {}'.format(email))) self.request.session.flash(u'Referral email sent to: {}'.format( ', '.join(appstruct['emails'].splitlines()))) return HTTPFound(location=self.request.route_path('referrals'))
def mail(request): """ Test email communication """ request.environ["HTTP_HOST"] = "appenlight.com" request.environ["wsgi.url_scheme"] = "https" renderer_vars = { "title": "You have just registered on AppEnlight", "username": "******", "email": "grzegżółka", "firstname": "dupa", } # return vars html = pyramid.renderers.render("/email_templates/registered.jinja2", renderer_vars, request=request) message = Message( subject="hello world %s" % random.randint(1, 9999), sender="*****@*****.**", recipients=["*****@*****.**"], html=html, ) request.registry.mailer.send(message) return html return vars
def confirmation(request): ''' Generates confirmation page and confirmation emails to user and D2L site admin. ''' if not logged_in(request): return HTTPFound(location=request.route_url('login')) form = SelectCoursesForm() csrf_token = request.session.get_csrf_token() submitter_email = request.session['uniqueName'] + '@' + \ request.registry.settings['EMAIL_DOMAIN'] name = request.session['firstName'] + ' ' + request.session['lastName'] sender = request.registry.settings['mail.username'] '''remove for production''' submitter_email = '*****@*****.**' message = Message(subject="Course Combine Confirmation", sender=sender, recipients=[sender, submitter_email]) message.body = make_msg_text(name, submitter_email, request) message.html = make_msg_html(name, submitter_email, request) mailer = get_mailer(request) mailer.send_immediately(message, fail_silently=False) return { 'csrf_token': csrf_token, 'name': name, 'form': form, 'base_course': request.session['base_course'], 'courses_to_combine': request.session['courses_to_combine'] }
def create_message(request, template, context, subject, recipients, attachments=None, extra_headers=None): text_body = render(template + '.txt', context, request=request) # chamaleon txt templates are rendered as utf-8 bytestrings text_body = text_body.decode('utf-8') html_body = render(template + '.pt', context, request=request) extra_headers = extra_headers or {} message = Message( subject=subject, recipients=recipients, body=text_body, html=html_body, extra_headers=extra_headers, ) if attachments is not None: for attachment in attachments: message.attach(attachment) return message
def email_set_password(user, request, template_name='kotti:templates/email-set-password.pt', add_query=None): site_title = get_settings()['kotti.site_title'] token = make_token(user) user.confirm_token = unicode(token) set_password_query = {'token': token, 'email': user.email} if add_query: set_password_query.update(add_query) url = '%s/@@set-password?%s' % ( request.application_url, urllib.urlencode(set_password_query), ) variables = dict( user_title=user.title, site_title=site_title, url=url, ) text = render(template_name, variables, request) subject, htmlbody = text.strip().split('\n', 1) subject = subject.replace('Subject:', '', 1).strip() html2text = HTML2Text() html2text.body_width = 0 textbody = html2text.handle(htmlbody).strip() message = Message( recipients=[u'"%s" <%s>' % (user.title, user.email)], # XXX naive? subject=subject, body=textbody, html=htmlbody, ) mailer = get_mailer() mailer.send(message)
def test_attach_as_html(self): from pyramid_mailer.message import Message from pyramid_mailer.message import Attachment charset = 'iso-8859-1' text_encoded = b'LaPe\xf1a' html_encoded = b'<p>' + text_encoded + b'</p>' html_text = html_encoded.decode(charset) transfer_encoding = 'quoted-printable' html = Attachment(data=html_text, transfer_encoding=transfer_encoding) msg = Message( subject="testing", sender="*****@*****.**", recipients=["*****@*****.**"], html=html, ) html_part = msg.to_message() self.assertEqual(html_part['Content-Type'], 'text/html; charset="iso-8859-1"') self.assertEqual(html_part['Content-Transfer-Encoding'], transfer_encoding) self.assertEqual(html_part.get_payload(), _qencode(html_encoded).decode('ascii'))
def mail_payment_reminder(request): """ Send a mail to a membership applicant reminding her about lack of **payment**. Headquarters is still waiting for the **bank transfer**. This view can only be used by staff. To be approved for membership applicants have to * **Transfer money** for the shares to acquire (at least one share). * Send the signed form back to headquarters. """ member = request.registry.member_information.get_member_by_id( request.matchdict['memberid']) email_subject, email_body = make_payment_reminder_email(member) message = Message(subject=email_subject, sender='*****@*****.**', recipients=[member.email], body=email_body) send_message(request, message) try: # if value is int member.sent_payment_reminder += 1 except TypeError: # pragma: no cover # if value was None (after migration of DB schema) member.sent_payment_reminder = 1 member.sent_payment_reminder_date = datetime.now() if 'detail' in request.referrer: return HTTPFound( request.route_url('detail', memberid=request.matchdict['memberid'])) else: return get_dashboard_redirect(request, member.id)
def test_to_message_multipart_with_b64encoding(self): from pyramid_mailer.message import Message, Attachment response = Message(recipients=['To'], sender='From', subject='Subject', body='Body', html='Html') this = os.path.abspath(__file__) with open(this, 'rb') as data: attachment = Attachment( filename=this, content_type='application/octet-stream', disposition='disposition', transfer_encoding='base64', data=data, ) response.attach(attachment) message = response.to_message() payload = message.get_payload()[1] self.assertEqual(payload.get('Content-Transfer-Encoding'), 'base64') self.assertEqual( payload.get_payload(), _bencode(self._read_filedata(this, 'rb')).decode('ascii'))
def smtpified(request, user, *args, **kwargs): sender = get_mailer(request) to = "{0} <{1}>".format(user.username, user.email) message = f(Message(recipients=[to]), *args, **kwargs) sender.send_immediately(message)
def send_set_password(user, request, templates='set-password', add_query=None): site_title = get_settings()['kotti.site_title'] token = make_token(user) user.confirm_token = unicode(token) set_password_query = {'token': token, 'email': user.email} if add_query: set_password_query.update(add_query) url = '%s/@@set-password?%s' % ( request.application_url, urllib.urlencode(set_password_query), ) variables = dict( user_title=user.title, site_title=site_title, url=url, ) if isinstance(templates, str): templates = message_templates[templates] message = Message( recipients=[u'"%s" <%s>' % (user.title, user.email)], # XXX naive? subject=templates['subject'] % variables, body=templates['body'] % variables, ) mailer = get_mailer() mailer.send(message)
def state_change_notification(meeting, event): """ Sends an email to [email protected] when a meeting changes state """ request = get_current_request() url = resource_url(meeting, request) sender = "%s <%s>" % (meeting.get_field_value('meeting_mail_name'), meeting.get_field_value('meeting_mail_address')) response = { 'title': meeting.get_field_value('title'), 'new_state': event.new_state.title().lower(), 'old_state': event.old_state.title().lower(), 'url': url, } body_html = render('views/templates/email/state_change_notification.pt', response, request=request) msg = Message(subject=_(u"VoteIT meeting state changed"), sender=sender and sender or None, recipients=("*****@*****.**", ), html=body_html) mailer = get_mailer(request) mailer.send(msg)
def send_templated_mail(request, recipients, template, context, sender=None): """Send out templatized HTML and plain text emails. Each HTML email should have a plain text fallback. Premailer package is used to convert any CSS styles in HTML email messages to inline, so that email clients display them. The email is assembled from three different templates: * Read subject from a subject specific template $template.subject.txt * Generate HTML email from HTML template, $template.body.html * Generate plain text email from HTML template, $template.body.txt Make sure you have configured your template engine (Jinja 2) to read TXT templates beside HTML. :param request: HTTP request, passed to the template engine. Request configuration is used to get hold of the configured mailer. :param recipients: List of recipient emails :param template: Template filename base string for template tripled (subject, HTML body, plain text body). For example ``email/my_message`` would map to templates ``email/my_message.subject.txt``, ``email/my_message.body.txt``, ``email/my_message.body.html`` :param context: Template context variables as a dict :param sender: Override the sender email - if not specific use the default set in the config as ``mail.default_sender`` """ assert recipients assert len(recipients) > 0 assert type( recipients) != str, "Please give a list of recipients, not a string" for r in recipients: assert r, "Received empty recipient when sending out email {}".format( template) subject = render(template + ".subject.txt", context, request=request) subject = subject.strip() html_body = render(template + ".body.html", context, request=request) text_body = render(template + ".body.txt", context, request=request) if not sender: sender = request.registry.settings["mail.default_sender"] # Add enveloped From: sender_name = request.registry.settings.get("mail.default_sender_name") if sender_name: sender = formataddr((str(Header(sender_name, 'utf-8')), sender)) # Inline CSS styles html_body = premailer.transform(html_body) message = Message(subject=subject, sender=sender, recipients=recipients, body=text_body, html=html_body) mailer = get_mailer(request) mailer.send(message)
def test_send_email_success(self, monkeypatch): message_obj = Message() def mock_message(*args, **kwargs): return message_obj monkeypatch.setattr(email, "Message", mock_message) task = pretend.stub() mailer = pretend.stub( send_immediately=pretend.call_recorder(lambda i: None) ) request = pretend.stub( registry=pretend.stub( settings=pretend.stub( get=pretend.call_recorder(lambda k: 'SENDER'), ), getUtility=pretend.call_recorder(lambda mailr: mailer) ) ) email.send_email(task, request, "body", ["recipients"], "subject") assert mailer.send_immediately.calls == [pretend.call(message_obj)] assert request.registry.getUtility.calls == [pretend.call(IMailer)] assert request.registry.settings.get.calls == [ pretend.call("mail.sender")]
def test_is_bad_headers_if_subject_empty(self): from pyramid_mailer.message import Message msg = Message(sender="*****@*****.**", body="testing", recipients=["*****@*****.**"]) self.assert_(not (msg.is_bad_headers()))
def email_profile_change_notification(event): if ('first_name' not in event.activity_detail and 'last_name' not in event.activity_detail): return same_user = event.actor == event.user if event.actor.is_superuser and not same_user: return first_name = event.activity_detail.get('first_name', '') last_name = event.activity_detail.get('last_name', '') logger = getLogger('speak_friend.user_activity') for key, value in event.activity_detail.items(): logger.info('%s changed their %s' % (event.user.username, key)) path = 'speak_friend:templates/email/account_change_notification.pt' settings = event.request.registry.settings subject = '%s: Account updated' % settings['site_name'] mailer = get_mailer(event.request) response = render_to_response(path, {'profile': event.user, 'first_name': first_name, 'last_name': last_name }, event.request) message = Message(subject=subject, sender=settings['site_from'], recipients=[event.user.full_email], html=response.unicode_body) mailer.send(message)
def forgot(request): _ = request.translate if request.method != 'POST' or 'username' not in request.POST: return {} u = DBSession.query(User) \ .filter_by(username=request.POST['username']) \ .first() if not u: request.messages.error(_('Unknown username.')) request.response.status_code = HTTPBadRequest.code return {} if not u.email: request.messages.error( _('No e-mail address associated with username.')) request.response.status_code = HTTPBadRequest.code return {} token = PasswordResetToken(u) DBSession.add(token) DBSession.flush() mailer = get_mailer(request) body = render('mail/password_reset.mako', { 'user': u, 'requested_by': request.remote_addr, 'url': request.route_url('account_reset', token=token.token) }, request=request) message = Message(subject=_('CCVPN: Password reset request'), recipients=[u.email], body=body) mailer.send(message) request.messages.info(_('We sent a reset link. Check your emails.')) return {}
def notify_account_created(event): """Notify site admins when an account is created. """ logger = getLogger('speak_friend.user_activity') path = 'speak_friend:templates/email/account_creation_notification.pt' settings = event.request.registry.settings subject = '%s: New user created' % settings['site_name'] mailer = get_mailer(event.request) headers = {'Reply-To': event.user.full_email} response = render_to_response(path, {'profile': event.user}, event.request) # Obtain list of emails to notify from the control panel cp = ControlPanel(event.request) recipients = cp.get_value(email_notification_schema.name, 'user_creation', []) if not recipients: logger.info('No one to notify of account creation: %s.', event.user) return message = Message(subject=subject, sender=settings['site_from'], recipients=recipients, extra_headers=headers, html=response.unicode_body) mailer.send(message)
def send_notification(self, email, subject, message): """Sends email notification to admins. Sends email with the pyramid_mailer module. For configuration look at documentation http://pythonhosted.org//pyramid_mailer/ """ from pyramid_mailer import get_mailer mailer = get_mailer(self.request) sender = "noreply@%s" % (self.request.server_name) recipients = set() for user in self.collection.find({'group': Admin}): email = user.get('email') if email: recipients.add(email) if len(recipients) > 0: from pyramid_mailer.message import Message message = Message(subject=subject, sender=sender, recipients=recipients, body=message) try: mailer.send_immediately(message, fail_silently=True) except Exception: LOGGER.error("failed to send notification") else: LOGGER.warn( "Can't send notification. No admin emails are available.")
def email_change_notification(event): if ('old_address' not in event.activity_detail and 'new_address' not in event.activity_detail): return same_user = event.actor == event.user if event.actor.is_superuser and not same_user: return old = event.activity_detail['old_address'] new = event.activity_detail['new_address'] logger = getLogger('speak_friend.user_activity') logger.info('%s changed their email address' % event.user.username) path = 'speak_friend:templates/email/account_email_change_notification.pt' settings = event.request.registry.settings subject = '%s: Email changed' % settings['site_name'] mailer = get_mailer(event.request) response = render_to_response(path, {'profile': event.user, 'old_address': old, 'new_address': new, }, event.request) message = Message(subject=subject, sender=settings['site_from'], recipients=[old, new], html=response.unicode_body) mailer.send(message)