def makeThrottledSender(self): sender = self.factory.makePerson(email='*****@*****.**') old_message = self.factory.makeSignedMessage(email_address='*****@*****.**') authorization = IDirectEmailAuthorization(sender) for action in xrange(authorization.message_quota): authorization.record(old_message) return sender
def makeThrottledSender(self): sender = self.factory.makePerson(email='*****@*****.**') old_message = self.factory.makeSignedMessage(email_address='*****@*****.**') authorization = IDirectEmailAuthorization(sender) for action in xrange(authorization.message_quota): authorization.record(old_message) return sender
def test_quota_reached_error(self): # An error is raised if the user has reached the daily quota. self.factory.makePerson(email='*****@*****.**', name='me') user = self.factory.makePerson(email='*****@*****.**', name='him') recipients_set = NotificationRecipientSet() old_message = self.factory.makeSignedMessage(email_address='*****@*****.**') authorization = IDirectEmailAuthorization(user) for action in xrange(authorization.message_quota): authorization.record(old_message) self.assertRaises(QuotaReachedError, send_direct_contact_email, '*****@*****.**', recipients_set, 'subject', 'body')
def test_quota_reached_error(self): # An error is raised if the user has reached the daily quota. self.factory.makePerson(email='*****@*****.**', name='me') user = self.factory.makePerson(email='*****@*****.**', name='him') recipients_set = NotificationRecipientSet() old_message = self.factory.makeSignedMessage(email_address='*****@*****.**') authorization = IDirectEmailAuthorization(user) for action in xrange(authorization.message_quota): authorization.record(old_message) self.assertRaises( QuotaReachedError, send_direct_contact_email, '*****@*****.**', recipients_set, 'subject', 'body')
def test_empty_recipient_set(self): # The recipient set can be empty. No messages are sent and the # action does not count toward the daily quota. self.factory.makePerson(email='*****@*****.**', name='me') user = self.factory.makePerson(email='*****@*****.**', name='him') recipients_set = NotificationRecipientSet() old_message = self.factory.makeSignedMessage(email_address='*****@*****.**') authorization = IDirectEmailAuthorization(user) for action in xrange(authorization.message_quota - 1): authorization.record(old_message) pop_notifications() send_direct_contact_email( '*****@*****.**', recipients_set, 'subject', 'body') notifications = pop_notifications() self.assertEqual(0, len(notifications)) self.assertTrue(authorization.is_allowed)
def test_empty_recipient_set(self): # The recipient set can be empty. No messages are sent and the # action does not count toward the daily quota. self.factory.makePerson(email='*****@*****.**', name='me') user = self.factory.makePerson(email='*****@*****.**', name='him') recipients_set = NotificationRecipientSet() old_message = self.factory.makeSignedMessage(email_address='*****@*****.**') authorization = IDirectEmailAuthorization(user) for action in xrange(authorization.message_quota - 1): authorization.record(old_message) pop_notifications() send_direct_contact_email('*****@*****.**', recipients_set, 'subject', 'body') notifications = pop_notifications() self.assertEqual(0, len(notifications)) self.assertTrue(authorization.is_allowed)
def send_direct_contact_email(sender_email, recipients_set, person_or_team, subject, body): """Send a direct user-to-user email. :param sender_email: The email address of the sender. :type sender_email: string :param recipients_set: The recipients. :type recipients_set: `ContactViaWebNotificationSet` :param person_or_team: The party that is the context of the email. :type person_or_team: `IPerson` :param subject: The Subject header. :type subject: unicode :param body: The message body. :type body: unicode :return: The sent message. :rtype: `email.message.Message` """ # Craft the email message. Start by checking whether the subject and # message bodies are ASCII or not. subject_header = encode(subject) try: body.encode('us-ascii') charset = 'us-ascii' except UnicodeEncodeError: charset = 'utf-8' # Get the sender's real name, encoded as per RFC 2047. person_set = getUtility(IPersonSet) sender = person_set.getByEmail(sender_email) assert sender is not None, 'No person for sender %s' % sender_email sender_name = str(encode(sender.displayname)) # Do a single authorization/quota check for the sender. We consume one # quota credit per contact, not per recipient. authorization = IDirectEmailAuthorization(sender) if not authorization.is_allowed: raise QuotaReachedError(sender.displayname, authorization) # Add the footer as a unicode string, then encode the body if necessary. # This is not entirely optimal if the body has non-ascii characters in it, # since the footer may get garbled in a non-MIME aware mail reader. Who # uses those anyway!? The only alternative is to attach the footer as a # MIME attachment with a us-ascii charset, but that has it's own set of # problems (and user complaints). Email sucks. additions = u'\n'.join([ u'', u'-- ', u'This message was sent from Launchpad by', u'%s (%s)' % (sender_name, canonical_url(sender)), u'%s.', u'For more information see', u'https://help.launchpad.net/YourAccount/ContactingPeople', ]) # Craft and send one message per recipient. mailwrapper = MailWrapper(width=72) message = None for recipient_email, recipient in recipients_set.getRecipientPersons(): recipient_name = str(encode(recipient.displayname)) reason, rationale_header = recipients_set.getReason(recipient_email) reason = str(encode(reason)).replace('\n ', '\n') formatted_body = mailwrapper.format(body, force_wrap=True) formatted_body += additions % reason formatted_body = formatted_body.encode(charset) message = MIMEText(formatted_body, _charset=charset) message['From'] = formataddr((sender_name, sender_email)) message['To'] = formataddr((recipient_name, recipient_email)) message['Subject'] = subject_header message['Message-ID'] = make_msgid('launchpad') message['X-Launchpad-Message-Rationale'] = rationale_header message['X-Launchpad-Message-For'] = person_or_team.name # Send the message. sendmail(message, bulk=False) # Use the information from the last message sent to record the action # taken. The record will be used to throttle user-to-user emails. if message is not None: authorization.record(message)
def send_direct_contact_email( sender_email, recipients_set, subject, body): """Send a direct user-to-user email. :param sender_email: The email address of the sender. :type sender_email: string :param recipients_set: The recipients. :type recipients_set:' A ContactViaWebNotificationSet :param subject: The Subject header. :type subject: unicode :param body: The message body. :type body: unicode :return: The sent message. :rtype: `email.Message.Message` """ # Craft the email message. Start by checking whether the subject and # message bodies are ASCII or not. subject_header = encode(subject) try: body.encode('us-ascii') charset = 'us-ascii' except UnicodeEncodeError: charset = 'utf-8' # Get the sender's real name, encoded as per RFC 2047. person_set = getUtility(IPersonSet) sender = person_set.getByEmail(sender_email) assert sender is not None, 'No person for sender %s' % sender_email sender_name = str(encode(sender.displayname)) # Do a single authorization/quota check for the sender. We consume one # quota credit per contact, not per recipient. authorization = IDirectEmailAuthorization(sender) if not authorization.is_allowed: raise QuotaReachedError(sender.displayname, authorization) # Add the footer as a unicode string, then encode the body if necessary. # This is not entirely optimal if the body has non-ascii characters in it, # since the footer may get garbled in a non-MIME aware mail reader. Who # uses those anyway!? The only alternative is to attach the footer as a # MIME attachment with a us-ascii charset, but that has it's own set of # problems (and user complaints). Email sucks. additions = u'\n'.join([ u'', u'-- ', u'This message was sent from Launchpad by', u'%s (%s)' % (sender_name, canonical_url(sender)), u'%s.', u'For more information see', u'https://help.launchpad.net/YourAccount/ContactingPeople', ]) # Craft and send one message per recipient. mailwrapper = MailWrapper(width=72) message = None for recipient_email, recipient in recipients_set.getRecipientPersons(): recipient_name = str(encode(recipient.displayname)) reason, rational_header = recipients_set.getReason(recipient_email) reason = str(encode(reason)).replace('\n ', '\n') formatted_body = mailwrapper.format(body, force_wrap=True) formatted_body += additions % reason formatted_body = formatted_body.encode(charset) message = MIMEText(formatted_body, _charset=charset) message['From'] = formataddr((sender_name, sender_email)) message['To'] = formataddr((recipient_name, recipient_email)) message['Subject'] = subject_header message['Message-ID'] = make_msgid('launchpad') message['X-Launchpad-Message-Rationale'] = rational_header # Send the message. sendmail(message, bulk=False) # Use the information from the last message sent to record the action # taken. The record will be used to throttle user-to-user emails. if message is not None: authorization.record(message)