def send_rsvp(ical_data, event, body_text, status, account): from inbox.sendmail.base import get_sendmail_client ical_file = ical_data["cal"] rsvp_to = ical_data["organizer_email"] ical_txt = ical_file.to_ical() sendmail_client = get_sendmail_client(account) msg = mime.create.multipart('mixed') body = mime.create.multipart('alternative') body.append( mime.create.text('plain', ''), mime.create.text('calendar;method=REPLY', ical_txt)) msg.append(body) msg.headers['Reply-To'] = account.email_address msg.headers['From'] = account.email_address # We actually send the reply to the invite's From: # address, because it works for most providers. # However, iCloud sends invites from [email protected] so we detect # this and send RSVPs to the organizer's email. Frustratingly, iCloud # doesn't seem to handle RSVPs at all, but at least the reply ends up # in the organizer's mailbox. assert event.message.from_addr is not None assert len(event.message.from_addr) == 1 from_addr = event.message.from_addr[0][1] if from_addr != '*****@*****.**': msg.headers['To'] = from_addr else: msg.headers['To'] = rsvp_to assert status in ['yes', 'no', 'maybe'] if status == 'yes': msg.headers['Subject'] = 'Accepted: {}'.format(event.message.subject) elif status == 'maybe': msg.headers['Subject'] = 'Tentatively accepted: {}'.format( event.message.subject) elif status == 'no': msg.headers['Subject'] = 'Declined: {}'.format(event.message.subject) final_message = msg.to_string() sendmail_client = get_sendmail_client(account) sendmail_client.send_generated_email([rsvp_to], final_message)
def send_invite(ical_txt, event, account, invite_type='request'): from inbox.sendmail.base import get_sendmail_client, SendMailException for participant in event.participants: email = participant.get('email', None) if email is None: continue msg = generate_invite_message(ical_txt, event, account, invite_type) msg.headers['To'] = email final_message = msg.to_string() try: sendmail_client = get_sendmail_client(account) sendmail_client.send_generated_email([email], final_message) except SendMailException as e: log.error("Couldnt send invite email for", email_address=email, event_id=event.id, account_id=account.id, logstash_tag='invite_sending', exception=str(e)) if (account.provider == 'eas' and not account.outlook_account and invite_type in ['request', 'update']): # Exchange very surprisingly goes out of the way to send an invite # to all participants (though Outlook.com doesn't). # We only do this for invites and not cancelled because Exchange # doesn't parse our cancellation messages as invites. break
def send_draft_copy(account, draft, custom_body, recipient): """ Sends a copy of this draft to the recipient, using the specified body rather that the one on the draft object, and not marking the draft as sent. Used within multi-send to send messages to individual recipients with customized bodies. """ # Create the response to send on success by serlializing the draft. After # serializing, we replace the new custom body (which the recipient will get # and which should be returned in this response) in place of the existing # body (which we still need to retain in the draft for when it's saved to # the sent folder). response_on_success = encode(draft) response_on_success["body"] = custom_body response_on_success = APIEncoder().jsonify(response_on_success) # Now send the draft to the specified recipient. The send_custom method # will write the custom body into the message in place of the one in the # draft. try: sendmail_client = get_sendmail_client(account) sendmail_client.send_custom(draft, custom_body, [recipient]) except SendMailException as exc: kwargs = {} if exc.failures: kwargs["failures"] = exc.failures if exc.server_error: kwargs["server_error"] = exc.server_error return err(exc.http_code, exc.args[0], **kwargs) return response_on_success
def send_draft_copy(account, draft, custom_body, recipient): """ Sends a copy of this draft to the recipient, using the specified body rather that the one on the draft object, and not marking the draft as sent. Used within multi-send to send messages to individual recipients with customized bodies. """ # Create the response to send on success by serlializing the draft. Before # serializing, we temporarily swap in the new custom body (which the # recipient will get and which should be returned in this response) in # place of the existing body (which we still need to retain in the draft # for when it's saved to the sent folder). We replace the existing body # after serialization is done. original_body = draft.body draft.body = custom_body response_on_success = APIEncoder().jsonify(draft) draft.body = original_body # Now send the draft to the specified recipient. The send_custom method # will write the custom body into the message in place of the one in the # draft. try: sendmail_client = get_sendmail_client(account) sendmail_client.send_custom(draft, custom_body, [recipient]) except SendMailException as exc: kwargs = {} if exc.failures: kwargs['failures'] = exc.failures if exc.server_error: kwargs['server_error'] = exc.server_error return err(exc.http_code, exc.message, **kwargs) return response_on_success
def _send(account_id, draft_id, db_session): """Send the draft with id = `draft_id`.""" account = db_session.query(Account).get(account_id) try: sendmail_client = get_sendmail_client(account) except SendMailException: log.error('Send Error', message="Failed to create sendmail client.", account_id=account_id) raise try: draft = db_session.query(Message).filter( Message.id == draft_id).one() except NoResultFound: log.info('Send Error', message='NoResultFound for draft_id {0}'.format(draft_id), account_id=account_id) raise SendMailException('No draft with id {0}'.format(draft_id)) except MultipleResultsFound: log.info('Send Error', message='MultipleResultsFound for draft_id' '{0}'.format(draft_id), account_id=account_id) raise SendMailException('Multiple drafts with id {0}'.format( draft_id)) if not draft.is_draft or draft.is_sent: return recipients = Recipients(draft.to_addr, draft.cc_addr, draft.bcc_addr) if not draft.is_reply: sendmail_client.send_new(db_session, draft, recipients) else: sendmail_client.send_reply(db_session, draft, recipients) if account.provider == 'icloud': # Special case because iCloud doesn't save # sent messages. schedule_action('save_sent_email', draft, draft.namespace.id, db_session) # Update message draft.is_sent = True draft.is_draft = False draft.state = 'sent' # Update thread sent_tag = account.namespace.tags['sent'] draft_tag = account.namespace.tags['drafts'] draft.thread.apply_tag(sent_tag) # Remove the drafts tag from the thread if there are no more drafts. if not draft.thread.drafts: draft.thread.remove_tag(draft_tag) return draft
def send_rsvp(ical_data, event, body_text, status, account): from inbox.sendmail.base import SendMailException, get_sendmail_client ical_file = ical_data["cal"] ical_txt = ical_file.to_ical() rsvp_to = rsvp_recipient(event) if rsvp_to is None: raise SendMailException("Couldn't find an organizer to RSVP to.") sendmail_client = get_sendmail_client(account) msg = mime.create.multipart("mixed") body = mime.create.multipart("alternative") body.append( mime.create.text("plain", ""), mime.create.text("calendar;method=REPLY", ical_txt), ) msg.append(body) msg.headers["Reply-To"] = account.email_address msg.headers["From"] = account.email_address msg.headers["To"] = rsvp_to assert status in ["yes", "no", "maybe"] if status == "yes": msg.headers["Subject"] = u"Accepted: {}".format(event.message.subject) elif status == "maybe": msg.headers["Subject"] = u"Tentatively accepted: {}".format( event.message.subject) elif status == "no": msg.headers["Subject"] = u"Declined: {}".format(event.message.subject) final_message = msg.to_string() sendmail_client = get_sendmail_client(account) sendmail_client.send_generated_email([rsvp_to], final_message)
def send_rsvp(ical_data, event, body_text, status, account): from inbox.sendmail.base import get_sendmail_client, SendMailException ical_file = ical_data["cal"] ical_txt = ical_file.to_ical() rsvp_to = rsvp_recipient(event) if rsvp_to is None: raise SendMailException("Couldn't find an organizer to RSVP to.") sendmail_client = get_sendmail_client(account) msg = mime.create.multipart('mixed') body = mime.create.multipart('alternative') body.append( mime.create.text('plain', ''), mime.create.text('calendar;method=REPLY', ical_txt)) msg.append(body) msg.headers['Reply-To'] = account.email_address msg.headers['From'] = account.email_address msg.headers['To'] = rsvp_to assert status in ['yes', 'no', 'maybe'] if status == 'yes': msg.headers['Subject'] = u'Accepted: {}'.format(event.message.subject) elif status == 'maybe': msg.headers['Subject'] = u'Tentatively accepted: {}'.format( event.message.subject) elif status == 'no': msg.headers['Subject'] = u'Declined: {}'.format(event.message.subject) final_message = msg.to_string() sendmail_client = get_sendmail_client(account) sendmail_client.send_generated_email([rsvp_to], final_message)
def send_draft(account_id, draft_id): """ Send the draft with id = `draft_id`. """ with session_scope() as db_session: account = db_session.query(Account).get(account_id) log = get_logger() sendmail_client = get_sendmail_client(account) try: draft = db_session.query(SpoolMessage).filter( SpoolMessage.id == draft_id).one() except NoResultFound: log.info('NoResultFound for draft_id {0}'.format(draft_id)) raise SendMailException('No draft with id {0}'.format(draft_id)) except MultipleResultsFound: log.info('MultipleResultsFound for draft_id {0}'.format(draft_id)) raise SendMailException('Multiple drafts with id {0}'.format( draft_id)) assert draft.is_draft and not draft.is_sent recipients = Recipients(draft.to_addr, draft.cc_addr, draft.bcc_addr) if not draft.is_reply: sendmail_client.send_new(db_session, draft, recipients) else: sendmail_client.send_reply(db_session, draft, recipients) # Update SpoolMessage draft.is_sent = True draft.is_draft = False draft.state = 'sent' # Update thread sent_tag = account.namespace.tags['sent'] draft_tag = account.namespace.tags['drafts'] draft.thread.apply_tag(sent_tag) # Remove the drafts tag from the thread if there are no more drafts. if not draft.thread.latest_drafts: draft.thread.remove_tag(draft_tag) db_session.commit() delete_draft(account_id, draft.id) return draft
def send_draft(account, draft, db_session, schedule_remote_delete): """Send the draft with id = `draft_id`.""" try: sendmail_client = get_sendmail_client(account) sendmail_client.send(draft) except SendMailException as exc: kwargs = {} if exc.failures: kwargs['failures'] = exc.failures if exc.server_error: kwargs['server_error'] = exc.server_error return err(exc.http_code, exc.message, **kwargs) # We want to return success to the API client if the message was sent, even # if there are errors in post-send updating. Otherwise the client may think # the send has failed. So wrap the rest of the work in try/except. try: if account.provider == 'icloud': # Special case because iCloud doesn't save sent messages. schedule_action('save_sent_email', draft, draft.namespace.id, db_session) if schedule_remote_delete: schedule_action('delete_draft', draft, draft.namespace.id, db_session, inbox_uid=draft.inbox_uid, message_id_header=draft.message_id_header) # Update message draft.is_sent = True draft.is_draft = False draft.received_date = datetime.utcnow() # Update thread sent_tag = account.namespace.tags['sent'] draft_tag = account.namespace.tags['drafts'] thread = draft.thread thread.apply_tag(sent_tag) # Remove the drafts tag from the thread if there are no more drafts. if not draft.thread.drafts: thread.remove_tag(draft_tag) thread.update_from_message(None, draft) except Exception as e: log.error('Error in post-send processing', error=e, exc_info=True) return APIEncoder().jsonify(draft)
def send_raw_mime(account, db_session, msg): # Prepare a response so that we can immediately return it on success, and # not potentially have queries fail after sending. response_on_success = APIEncoder().jsonify(msg) try: sendmail_client = get_sendmail_client(account) sendmail_client.send_raw(msg) except SendMailException as exc: kwargs = {} if exc.failures: kwargs['failures'] = exc.failures if exc.server_error: kwargs['server_error'] = exc.server_error return err(exc.http_code, exc.message, **kwargs) return response_on_success
def send_draft(account, draft, db_session): """Send the draft with id = `draft_id`.""" # Update message state and prepare a response so that we can immediately # return it on success, and not potentially have queries fail after # sending. Note that changes are flushed here, but committed in the API's # after_request handler only on 200 OK (hence only if sending succeeds). update_draft_on_send(account, draft, db_session) response_on_success = APIEncoder().jsonify(draft) try: sendmail_client = get_sendmail_client(account) sendmail_client.send(draft) except SendMailException as exc: kwargs = {} if exc.failures: kwargs['failures'] = exc.failures if exc.server_error: kwargs['server_error'] = exc.server_error return err(exc.http_code, exc.message, **kwargs) return response_on_success
def _send(account_id, draft_id, db_session): """Send the draft with id = `draft_id`.""" account = db_session.query(Account).get(account_id) sendmail_client = get_sendmail_client(account) try: draft = db_session.query(Message).filter( Message.id == draft_id).one() except NoResultFound: log.info('NoResultFound for draft_id {0}'.format(draft_id)) raise SendMailException('No draft with id {0}'.format(draft_id)) except MultipleResultsFound: log.info('MultipleResultsFound for draft_id {0}'.format(draft_id)) raise SendMailException('Multiple drafts with id {0}'.format( draft_id)) if not draft.is_draft or draft.is_sent: return recipients = Recipients(draft.to_addr, draft.cc_addr, draft.bcc_addr) if not draft.is_reply: sendmail_client.send_new(db_session, draft, recipients) else: sendmail_client.send_reply(db_session, draft, recipients) # Update message draft.is_sent = True draft.is_draft = False draft.state = 'sent' # Update thread sent_tag = account.namespace.tags['sent'] draft_tag = account.namespace.tags['drafts'] draft.thread.apply_tag(sent_tag) # Remove the drafts tag from the thread if there are no more drafts. if not draft.thread.drafts: draft.thread.remove_tag(draft_tag) return draft
def _send(account_id, draft_id, db_session): """Send the draft with id = `draft_id`.""" account = db_session.query(Account).get(account_id) log = get_logger() sendmail_client = get_sendmail_client(account) try: draft = db_session.query(Message).filter(Message.id == draft_id).one() except NoResultFound: log.info('NoResultFound for draft_id {0}'.format(draft_id)) raise SendMailException('No draft with id {0}'.format(draft_id)) except MultipleResultsFound: log.info('MultipleResultsFound for draft_id {0}'.format(draft_id)) raise SendMailException('Multiple drafts with id {0}'.format(draft_id)) if not draft.is_draft or draft.is_sent: return recipients = Recipients(draft.to_addr, draft.cc_addr, draft.bcc_addr) if not draft.is_reply: sendmail_client.send_new(db_session, draft, recipients) else: sendmail_client.send_reply(db_session, draft, recipients) # Update message draft.is_sent = True draft.is_draft = False draft.state = 'sent' # Update thread sent_tag = account.namespace.tags['sent'] draft_tag = account.namespace.tags['drafts'] draft.thread.apply_tag(sent_tag) # Remove the drafts tag from the thread if there are no more drafts. if not draft.thread.drafts: draft.thread.remove_tag(draft_tag) return draft