示例#1
0
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)
示例#2
0
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)
示例#3
0
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
示例#4
0
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
示例#5
0
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
示例#6
0
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
示例#7
0
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
示例#8
0
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)
示例#9
0
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)
示例#10
0
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)
示例#11
0
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
示例#12
0
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)
示例#13
0
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
示例#14
0
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)
示例#15
0
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
示例#16
0
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
示例#17
0
文件: __init__.py 项目: rbs-pli/inbox
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