def get(self, request): # Get the state param from the request. state = str(request.GET.get('state')) # Replace %xx characters with single quotes and UTF8 decode the string. state = urllib.unquote(state).decode('utf8') # Deserialize the JSON string. state = anyjson.deserialize(b64decode(state)) if not validate_token(settings.SECRET_KEY, state.get('token'), request.user.pk): return HttpResponseBadRequest() error = request.GET.get('error') if error: messages.error( self.request, _('Sorry, Lily needs authorization from Google to synchronize your email account.' )) return HttpResponseRedirect('/#/preferences/emailaccounts') credentials = FLOW.step2_exchange(code=request.GET.get('code')) # Setup service to retrieve email address. service = build_gmail_service(credentials) profile = service.users().getProfile(userId='me').execute() # Create account based on email address. account, created = EmailAccount.objects.get_or_create( owner=request.user, email_address=profile.get('emailAddress')) # Store credentials based on new email account. storage = Storage(GmailCredentialsModel, 'id', account, 'credentials') storage.put(credentials) # Set account as authorized. account.is_authorized = True account.is_deleted = False account.label = account.label or account.email_address account.from_name = account.from_name or ' '.join( account.email_address.split('@')[0].split('.')).title() set_to_public = bool(int(state.get('public'))) if account.public is not set_to_public: account.public = set_to_public only_sync_new_mails = bool(int(state.get('only_new'))) if only_sync_new_mails and created: # Setting it before the first sync means it will only fetch changes starting now. account.history_id = profile.get('historyId') account.full_sync_finished = True account.save() post_intercom_event(event_name='email-account-added', user_id=request.user.id) return HttpResponseRedirect('/#/preferences/emailaccounts/edit/%s' % account.pk)
def formset_valid(self, formset): """ This function is called when the formset is deemed valid. An email is sent to all email fields which are filled in. If the request is done via ajax give json back with a success message, otherwise redirect to the success url. """ protocol = self.request.is_secure() and 'https' or 'http' date_string = date.today().strftime('%d%m%Y') # Get the current site or empty string try: current_site = Site.objects.get_current() except Site.DoesNotExist: current_site = '' for form in formset: if form in formset.deleted_forms: continue first_name = form.cleaned_data.get('first_name') email = form.cleaned_data.get('email') tenant_id = self.request.user.tenant_id hash = sha256('%s-%s-%s-%s' % ( tenant_id, email, date_string, settings.SECRET_KEY )).hexdigest() invite_link = '%s://%s%s' % (protocol, current_site, reverse_lazy('invitation_accept', kwargs={ 'tenant_id': tenant_id, 'first_name': first_name, 'email': email, 'date': date_string, 'hash': hash, })) # Email to the user send_templated_mail( template_name='invitation', from_email=settings.DEFAULT_FROM_EMAIL, recipient_list=[form.cleaned_data['email']], context={ 'current_site': current_site, 'full_name': self.request.user.full_name, 'name': first_name, 'invite_link': invite_link, } ) post_intercom_event(event_name='invite-sent', user_id=self.request.user.id) if is_ajax(self.request): return HttpResponse(anyjson.serialize({ 'error': False, 'html': _('The invitations were sent successfully'), }), content_type='application/json') return HttpResponseRedirect(self.get_success_url())
def get(self, request): # Get the state param from the request. state = str(request.GET.get('state')) # Replace %xx characters with single quotes and UTF8 decode the string. state = urllib.unquote(state).decode('utf8') # Deserialize the JSON string. state = anyjson.deserialize(b64decode(state)) if not validate_token(settings.SECRET_KEY, state.get('token'), request.user.pk): return HttpResponseBadRequest() error = request.GET.get('error') if error: messages.error( self.request, _('Sorry, Lily needs authorization from Google to synchronize your email account.') ) return HttpResponseRedirect('/#/preferences/emailaccounts') credentials = FLOW.step2_exchange(code=request.GET.get('code')) # Setup service to retrieve email address. service = build_gmail_service(credentials) profile = service.users().getProfile(userId='me').execute() # Create account based on email address. account, created = EmailAccount.objects.get_or_create( owner=request.user, email_address=profile.get('emailAddress') ) # Store credentials based on new email account. storage = Storage(GmailCredentialsModel, 'id', account, 'credentials') storage.put(credentials) # Set account as authorized. account.is_authorized = True account.is_deleted = False account.label = account.label or account.email_address account.from_name = account.from_name or ' '.join(account.email_address.split('@')[0].split('.')).title() set_to_public = bool(int(state.get('public'))) if account.public is not set_to_public: account.public = set_to_public only_sync_new_mails = bool(int(state.get('only_new'))) if only_sync_new_mails and created: # Setting it before the first sync means it will only fetch changes starting now. account.history_id = profile.get('historyId') account.first_sync_finished = True account.save() post_intercom_event(event_name='email-account-added', user_id=request.user.id) return HttpResponseRedirect('/#/preferences/emailaccounts/edit/%s' % account.pk)
def form_valid(self, form): # Saves instance response = super(CreateEmailTemplateView, self).form_valid(form) # Show save messages message = _('%s has been created.') % self.object.name messages.success(self.request, message) post_intercom_event(event_name='email-template-created', user_id=self.request.user.id) return response
def send_message(email_outbox_message_id, original_message_id=None): """ Send EmailOutboxMessage. Args: email_outbox_message_id (int): id of the EmailOutboxMessage original_message_id (int, optional): ID of the original EmailMessage """ send_logger = logging.getLogger('email_errors_temp_logger') send_logger.info('Start sending email_outbox_message: %d' % (email_outbox_message_id, )) sent_success = False try: email_outbox_message = EmailOutboxMessage.objects.get( pk=email_outbox_message_id) except EmailOutboxMessage.DoesNotExist: raise email_account = email_outbox_message.send_from if not email_account.is_authorized: logger.error('EmailAccount not authorized: %s', email_account) return sent_success # If we reply or forward, we want to add the thread_id. original_message_thread_id = None if original_message_id: try: original_message = EmailMessage.objects.get(pk=original_message_id) if original_message.account.id is email_account.id: original_message_thread_id = original_message.thread_id except EmailMessage.DoesNotExist: raise # Add template attachments. if email_outbox_message.template_attachment_ids: template_attachment_id_list = email_outbox_message.template_attachment_ids.split( ',') for template_attachment_id in template_attachment_id_list: try: template_attachment = EmailTemplateAttachment.objects.get( pk=template_attachment_id) except EmailTemplateAttachment.DoesNotExist: pass else: attachment = EmailOutboxAttachment() attachment.content_type = template_attachment.content_type attachment.size = template_attachment.size attachment.email_outbox_message = email_outbox_message attachment.attachment = template_attachment.attachment attachment.tenant_id = template_attachment.tenant_id attachment.save() # Add attachment from original message (if mail is being forwarded). if email_outbox_message.original_attachment_ids: original_attachment_id_list = email_outbox_message.original_attachment_ids.split( ',') for attachment_id in original_attachment_id_list: try: original_attachment = EmailAttachment.objects.get( pk=attachment_id) except EmailAttachment.DoesNotExist: pass else: outbox_attachment = EmailOutboxAttachment() outbox_attachment.email_outbox_message = email_outbox_message outbox_attachment.tenant_id = original_attachment.message.tenant_id file = default_storage._open( original_attachment.attachment.name) file.open() content = file.read() file.close() file = ContentFile(content) file.name = original_attachment.attachment.name outbox_attachment.attachment = file outbox_attachment.inline = original_attachment.inline outbox_attachment.size = file.size outbox_attachment.save() manager = None try: manager = GmailManager(email_account) manager.send_email_message(email_outbox_message.message(), original_message_thread_id) logger.debug('Message sent from: %s', email_account) # Seems like everything went right, so the EmailOutboxMessage object isn't needed any more. email_outbox_message.delete() sent_success = True # TODO: This should probably be moved to the front end once # we can notify users about sent mails. post_intercom_event(event_name='email-sent', user_id=email_account.owner.id) except HttpAccessTokenRefreshError: logger.warning('EmailAccount not authorized: %s', email_account) pass except Exception as e: logger.error(traceback.format_exc(e)) raise finally: if manager: manager.cleanup() send_logger.info( 'Done sending email_outbox_message: %d And sent_succes value: %s' % (email_outbox_message_id, sent_success)) return sent_success
def get(self, request): error = request.GET.get('error') if error: messages.error( self.request, _('Sorry, Lily needs authorization from Google to synchronize your email account.') ) return HttpResponseRedirect('/#/preferences/emailaccounts') # Get the state param from the request. state = str(request.GET.get('state')) # Replace %xx characters with single quotes and UTF8 decode the string. state = urllib.unquote(state).decode('utf8') # Deserialize the JSON string. state = anyjson.deserialize(b64decode(state)) if not validate_token(settings.SECRET_KEY, state.get('token'), request.user.pk): return HttpResponseBadRequest() credentials = FLOW.step2_exchange(code=request.GET.get('code')) # Setup service to retrieve email address from Google. gmail_service = GmailService(credentials) try: profile = gmail_service.execute_service(gmail_service.service.users().getProfile(userId='me')) except HttpError as error: error = anyjson.loads(error.content) error = error.get('error', error) if error.get('code') == 400 and error.get('message') == 'Mail service not enabled': messages.error(self.request, _('Mail is not enabled for this email account.')) else: messages.error(self.request, error.get('message')) if not request.user.info.registration_finished: # User is still busy with registration, so redirect to email account setup step again. return HttpResponseRedirect(reverse('register_email_account_setup')) else: return HttpResponseRedirect('/#/preferences/emailaccounts') # Create account based on email address. try: account, created = EmailAccount.objects.get_or_create( owner=request.user, tenant_id=request.user.tenant_id, email_address=profile.get('emailAddress') ) except EmailAccount.MultipleObjectsReturned: account, created = EmailAccount.objects.get_or_create( owner=request.user, tenant_id=request.user.tenant_id, email_address=profile.get('emailAddress'), is_deleted=False ) # Store credentials based on new email account. storage = Storage(GmailCredentialsModel, 'id', account, 'credentials') storage.put(credentials) account.is_deleted = False if request.user.tenant.billing.is_free_plan: account.privacy = EmailAccount.PRIVATE if created: account.only_new = None account.save() post_intercom_event(event_name='email-account-added', user_id=request.user.id) if not request.user.info.registration_finished: # User is still busy with registration, so redirect to the next step in the flow. return HttpResponseRedirect(reverse('register_email_account_details')) else: return HttpResponseRedirect('/#/preferences/emailaccounts/edit/%s' % account.pk)
def create(self, request): protocol = self.request.is_secure() and 'https' or 'http' date_string = date.today().strftime('%d%m%Y') tenant_id = self.request.user.tenant_id # Get the current site or empty string. try: current_site = Site.objects.get_current() except Site.DoesNotExist: current_site = '' invites = request.data.get('invites') errors = [] has_errors = False for invite in invites: first_name = invite.get('first_name') email = invite.get('email') valid_email = True error = {} try: validate_email(email) except: valid_email = False if not first_name or not email or not valid_email: error = { 'name': [_('Please enter a first name and valid email address')], } has_errors = True if LilyUser.objects.filter(email=email, is_active=True).exists(): error = { 'name': [_('A user with this email address already exists')], } has_errors = True errors.append(error) if UserInvite.objects.filter(email=email).exists(): # Send a new invite if one was already sent. UserInvite.objects.filter(email=email).delete() if has_errors: return Response({'invites': errors}, status=status.HTTP_400_BAD_REQUEST) for invite in invites: first_name = invite.get('first_name') email = invite.get('email') params = { 'first_name': first_name, 'email': email, } invite = UserInvite.objects.filter(**params).first() # An invite was already sent, so delete the old one. if invite: invite.delete() # We always want to create a new invite. invite = UserInvite.objects.create(**params) hash = sha256('%s-%s-%s-%s-%s' % (tenant_id, invite.id, email, date_string, settings.SECRET_KEY)).hexdigest() invite_link = '%s://%s%s' % (protocol, current_site, reverse_lazy( 'invitation_accept', kwargs={ 'tenant_id': tenant_id, 'first_name': first_name, 'email': email, 'date': date_string, 'hash': hash, })) # Email to the user. send_templated_mail( template_name='users/email/invitation.email', recipient_list=[email], context={ 'current_site': current_site, 'inviter_full_name': self.request.user.full_name, 'inviter_first_name': self.request.user.first_name, 'recipient_first_name': first_name, 'invite_link': invite_link, }, from_email=settings.EMAIL_PERSONAL_HOST_USER, auth_user=settings.EMAIL_PERSONAL_HOST_USER, auth_password=settings.EMAIL_PERSONAL_HOST_PASSWORD) if len(invites): post_intercom_event(event_name='invite-sent', user_id=self.request.user.id) return Response(status=status.HTTP_200_OK)
def create(self, request): protocol = self.request.is_secure() and 'https' or 'http' date_string = date.today().strftime('%d%m%Y') tenant_id = self.request.user.tenant_id # Get the current site or empty string. try: current_site = Site.objects.get_current() except Site.DoesNotExist: current_site = '' invites = request.data.get('invites') errors = [] has_errors = False for invite in invites: first_name = invite.get('first_name') email = invite.get('email') valid_email = True error = {} try: validate_email(email) except: valid_email = False if not first_name or not email or not valid_email: error = { 'name': [_('Please enter a first name and valid email address')], } has_errors = True if LilyUser.objects.filter(email=email, is_active=True).exists(): error = { 'name': [_('A user with this email address already exists')], } has_errors = True errors.append(error) if UserInvite.objects.filter(email=email).exists(): # Send a new invite if one was already sent. UserInvite.objects.filter(email=email).delete() if has_errors: return Response({'invites': errors}, status=status.HTTP_400_BAD_REQUEST) for invite in invites: first_name = invite.get('first_name') email = invite.get('email') params = { 'first_name': first_name, 'email': email, } invite = UserInvite.objects.filter(**params).first() # An invite was already sent, so delete the old one. if invite: invite.delete() # We always want to create a new invite. invite = UserInvite.objects.create(**params) hash = sha256('%s-%s-%s-%s-%s' % ( tenant_id, invite.id, email, date_string, settings.SECRET_KEY )).hexdigest() invite_link = '%s://%s%s' % (protocol, current_site, reverse_lazy('invitation_accept', kwargs={ 'tenant_id': tenant_id, 'first_name': first_name, 'email': email, 'date': date_string, 'hash': hash, })) # Email to the user. send_templated_mail( template_name='users/email/invitation.email', recipient_list=[email], context={ 'current_site': current_site, 'inviter_full_name': self.request.user.full_name, 'inviter_first_name': self.request.user.first_name, 'recipient_first_name': first_name, 'invite_link': invite_link, }, from_email=settings.EMAIL_PERSONAL_HOST_USER, auth_user=settings.EMAIL_PERSONAL_HOST_USER, auth_password=settings.EMAIL_PERSONAL_HOST_PASSWORD ) if len(invites): post_intercom_event(event_name='invite-sent', user_id=self.request.user.id) return Response(status=status.HTTP_200_OK)
def get(self, request): error = request.GET.get('error') if error: messages.error( self.request, _('Sorry, Lily needs authorization from Google to synchronize your email account.' )) return HttpResponseRedirect('/#/preferences/emailaccounts') # Get the state param from the request. state = str(request.GET.get('state')) # Replace %xx characters with single quotes and UTF8 decode the string. state = urllib.unquote(state).decode('utf8') # Deserialize the JSON string. state = anyjson.deserialize(b64decode(state)) if not validate_token(settings.SECRET_KEY, state.get('token'), request.user.pk): return HttpResponseBadRequest() credentials = FLOW.step2_exchange(code=request.GET.get('code')) # Setup service to retrieve email address from Google. gmail_service = GmailService(credentials) try: profile = gmail_service.execute_service( gmail_service.service.users().getProfile(userId='me')) except HttpError as error: error = anyjson.loads(error.content) error = error.get('error', error) if error.get('code') == 400 and error.get( 'message') == 'Mail service not enabled': messages.error( self.request, _('Mail is not enabled for this email account.')) else: messages.error(self.request, error.get('message')) # Adding email account failed, administer it as skipping the email setup or otherwise the user will be # stuck in redirect loop. user = self.request.user user.info.email_account_status = UserInfo.SKIPPED user.info.save() return HttpResponseRedirect('/#/preferences/emailaccounts') # Create account based on email address. try: account, created = EmailAccount.objects.get_or_create( owner=request.user, tenant_id=request.user.tenant_id, email_address=profile.get('emailAddress')) except EmailAccount.MultipleObjectsReturned: account, created = EmailAccount.objects.get_or_create( owner=request.user, tenant_id=request.user.tenant_id, email_address=profile.get('emailAddress'), is_deleted=False) # Store credentials based on new email account. storage = Storage(GmailCredentialsModel, 'id', account, 'credentials') storage.put(credentials) account.is_deleted = False if request.user.tenant.billing.is_free_plan: account.privacy = EmailAccount.PRIVATE if created: account.only_new = None account.save() post_intercom_event(event_name='email-account-added', user_id=request.user.id) if request.user.info and not request.user.info.email_account_status: # First time setup, so we want a different view. return HttpResponseRedirect( '/#/preferences/emailaccounts/setup/%s' % account.pk) else: return HttpResponseRedirect( '/#/preferences/emailaccounts/edit/%s' % account.pk)
def formset_valid(self, formset): """ This function is called when the formset is deemed valid. An email is sent to all email fields which are filled in. If the request is done via ajax give json back with a success message, otherwise redirect to the success url. """ protocol = self.request.is_secure() and 'https' or 'http' date_string = date.today().strftime('%d%m%Y') # Get the current site or empty string try: current_site = Site.objects.get_current() except Site.DoesNotExist: current_site = '' for form in formset: if form in formset.deleted_forms: continue first_name = form.cleaned_data.get('first_name') email = form.cleaned_data.get('email') tenant_id = self.request.user.tenant_id hash = sha256('%s-%s-%s-%s' % (tenant_id, email, date_string, settings.SECRET_KEY)).hexdigest() invite_link = '%s://%s%s' % (protocol, current_site, reverse_lazy( 'invitation_accept', kwargs={ 'tenant_id': tenant_id, 'first_name': first_name, 'email': email, 'date': date_string, 'hash': hash, })) # Email to the user send_templated_mail( template_name='invitation', recipient_list=[form.cleaned_data['email']], context={ 'current_site': current_site, 'inviter_full_name': self.request.user.full_name, 'inviter_first_name': self.request.user.first_name, 'recipient_first_name': first_name, 'invite_link': invite_link, }, from_email=settings.EMAIL_PERSONAL_HOST_USER, auth_user=settings.EMAIL_PERSONAL_HOST_USER, auth_password=settings.EMAIL_PERSONAL_HOST_PASSWORD) post_intercom_event(event_name='invite-sent', user_id=self.request.user.id) if is_ajax(self.request): return HttpResponse(anyjson.serialize({ 'error': False, 'html': _('The invitations were sent successfully'), }), content_type='application/json') return HttpResponseRedirect(self.get_success_url())
def send_message(email_id, original_message_id=None, draft=False): """ Send EmailOutboxMessage or EmailDraft. Args: email_outbox_message_id (int): id of the EmailOutboxMessage original_message_id (int, optional): ID of the original EmailMessage draft (bool, optional): whether the newer EmailDraft should be queried """ send_logger = logging.getLogger('email_errors_temp_logger') send_logger.info('Start sending email_outbox_message: %d' % (email_id,)) # Below describes the differences between EmailOutboxMessage and EmailDraft. # As soon as EmailDraft is proven to work, this class can be refactored to only work for EmailDraft. email_class = EmailOutboxMessage email_attachment_class = EmailOutboxAttachment email_attachment_to_email_class_field_name = 'email_outbox_message' email_message_function_name = 'message' if draft: email_class = EmailDraft email_attachment_class = EmailDraftAttachment email_attachment_to_email_class_field_name = 'email_draft' email_message_function_name = 'mime_message' sent_success = False try: email = email_class.objects.get(pk=email_id) except email_class.DoesNotExist: raise email_account = email.send_from if not email_account.is_authorized: logger.error('EmailAccount not authorized: %s', email_account) return sent_success # If we reply or forward, we want to add the thread_id. original_message_thread_id = None if original_message_id: try: original_message = EmailMessage.objects.get(pk=original_message_id) if original_message.account.id is email_account.id: original_message_thread_id = original_message.thread_id except EmailMessage.DoesNotExist: raise # Add template attachments. if email.template_attachment_ids: template_attachment_id_list = email.template_attachment_ids.split(',') for template_attachment_id in template_attachment_id_list: try: template_attachment = EmailTemplateAttachment.objects.get(pk=template_attachment_id) except EmailTemplateAttachment.DoesNotExist: pass else: attachment = email_attachment_class() attachment.content_type = template_attachment.content_type attachment.size = template_attachment.size setattr(attachment, email_attachment_to_email_class_field_name, email) attachment.attachment = template_attachment.attachment attachment.tenant_id = template_attachment.tenant_id attachment.save() # Add attachment from original message (if mail is being forwarded). if email.original_attachment_ids: original_attachment_id_list = email.original_attachment_ids.split(',') for attachment_id in original_attachment_id_list: try: original_attachment = EmailAttachment.objects.get(pk=attachment_id) except EmailAttachment.DoesNotExist: pass else: outbox_attachment = email_attachment_class() setattr(outbox_attachment, email_attachment_to_email_class_field_name, email) outbox_attachment.tenant_id = original_attachment.message.tenant_id file = default_storage._open(original_attachment.attachment.name) file.open() content = file.read() file.close() file = ContentFile(content) file.name = original_attachment.attachment.name outbox_attachment.attachment = file outbox_attachment.inline = original_attachment.inline outbox_attachment.size = file.size outbox_attachment.save() manager = None try: manager = GmailManager(email_account) manager.send_email_message(getattr(email, email_message_function_name)(), original_message_thread_id) logger.debug('Message sent from: %s', email_account) # Seems like everything went right, so the EmailOutboxMessage object isn't needed any more. email.delete() sent_success = True # TODO: This should probably be moved to the front end once # we can notify users about sent mails. post_intercom_event(event_name='email-sent', user_id=email_account.owner.id) except HttpAccessTokenRefreshError: logger.warning('EmailAccount not authorized: %s', email_account) pass except Exception as e: logger.error(traceback.format_exc(e)) raise finally: if manager: manager.cleanup() send_logger.info('Done sending {}: {} And sent_succes value: {}'.format( email_attachment_to_email_class_field_name, email_id, sent_success )) return sent_success
def send_message(email_outbox_message_id, original_message_id=None): """ Send EmailOutboxMessage. Args: email_outbox_message_id (int): id of the EmailOutboxMessage original_message_id (int, optional): ID of the original EmailMessage """ send_logger = logging.getLogger('email_errors_temp_logger') send_logger.info('Start sending email_outbox_message: %d' % (email_outbox_message_id,)) sent_success = False try: email_outbox_message = EmailOutboxMessage.objects.get(pk=email_outbox_message_id) except EmailOutboxMessage.DoesNotExist: raise email_account = email_outbox_message.send_from if not email_account.is_authorized: logger.error('EmailAccount not authorized: %s', email_account) return sent_success # If we reply or forward, we want to add the thread_id. original_message_thread_id = None if original_message_id: try: original_message = EmailMessage.objects.get(pk=original_message_id) if original_message.account.id is email_account.id: original_message_thread_id = original_message.thread_id except EmailMessage.DoesNotExist: raise # Add template attachments. if email_outbox_message.template_attachment_ids: template_attachment_id_list = email_outbox_message.template_attachment_ids.split(',') for template_attachment_id in template_attachment_id_list: try: template_attachment = EmailTemplateAttachment.objects.get(pk=template_attachment_id) except EmailTemplateAttachment.DoesNotExist: pass else: attachment = EmailOutboxAttachment() attachment.content_type = template_attachment.content_type attachment.size = template_attachment.size attachment.email_outbox_message = email_outbox_message attachment.attachment = template_attachment.attachment attachment.tenant_id = template_attachment.tenant_id attachment.save() # Add attachment from original message (if mail is being forwarded). if email_outbox_message.original_attachment_ids: original_attachment_id_list = email_outbox_message.original_attachment_ids.split(',') for attachment_id in original_attachment_id_list: try: original_attachment = EmailAttachment.objects.get(pk=attachment_id) except EmailAttachment.DoesNotExist: pass else: outbox_attachment = EmailOutboxAttachment() outbox_attachment.email_outbox_message = email_outbox_message outbox_attachment.tenant_id = original_attachment.message.tenant_id file = default_storage._open(original_attachment.attachment.name) file.open() content = file.read() file.close() file = ContentFile(content) file.name = original_attachment.attachment.name outbox_attachment.attachment = file outbox_attachment.inline = original_attachment.inline outbox_attachment.size = file.size outbox_attachment.save() manager = None try: manager = GmailManager(email_account) manager.send_email_message(email_outbox_message.message(), original_message_thread_id) logger.debug('Message sent from: %s', email_account) # Seems like everything went right, so the EmailOutboxMessage object isn't needed any more. email_outbox_message.delete() sent_success = True # TODO: This should probably be moved to the front end once # we can notify users about sent mails. post_intercom_event(event_name='email-sent', user_id=email_account.owner.id) except HttpAccessTokenRefreshError: logger.warning('EmailAccount not authorized: %s', email_account.email_address) pass except Exception as e: logger.error(traceback.format_exc(e)) raise finally: if manager: manager.cleanup() send_logger.info( 'Done sending email_outbox_message: %d And sent_succes value: %s' % (email_outbox_message_id, sent_success) ) return sent_success