def send_emails(email_id): members_not_sent_to = dao_get_members_not_sent_to(email_id) if current_app.config.get('EMAIL_RESTRICT'): limit = 1 elif current_app.config.get('ENVIRONMENT') == 'live': email_provider = get_email_provider() limit = email_provider.limit else: limit = current_app.config.get('EMAIL_LIMIT') current_app.logger.info( 'Task send_emails received %s, sending %d emails', str(email_id), len(members_not_sent_to) if len(members_not_sent_to) < limit else limit) email = dao_get_email_by_id(email_id) try: for index, (member_id, email_to) in enumerate(members_not_sent_to): if limit and index > limit - 1 or email.email_state != APPROVED: current_app.logger.info("Email stopped - {}".format( "not approved" if email.email_state != APPROVED else f"limit reached: {limit}")) break subject = email.get_subject() message = None if email.email_type == EVENT: message = get_email_html(email.email_type, event_id=email.event_id, details=email.details, extra_txt=email.extra_txt, member_id=member_id) elif email.email_type == MAGAZINE: message = get_email_html(MAGAZINE, magazine_id=email.magazine_id, member_id=member_id) email_status_code, email_provider_id = send_email( email_to, subject, message) dao_add_member_sent_to_email(email_id, member_id, status_code=email_status_code, email_provider_id=email_provider_id) send_ga_event( f"Sent {email.email_type} email, {subject} - {str(email.id)}", "email", "send success" if email_status_code in [200, 201, 202] else "send failed", f"{subject} - {email.id}") except InvalidRequest as e: if e.status_code == 429: current_app.logger.error("Email limit reached: %r", e.message) if "Minute" in e.message: send_periodic_emails.apply_async(countdown=60) raise
def reserve_place(): data = request.get_json(force=True) validate(data, post_reserve_place_schema) if dao_has_reserved_place(data['name'], data['email'], data['eventdate_id']): return jsonify( {"error": f"{data['name']} has already reserved a place"}) reserved_place = ReservedPlace(eventdate_id=data['eventdate_id'], name=data['name'], email=data['email']) current_app.logger.info("Reserved place %r", reserved_place.serialize()) dao_create_reserve_place(reserved_place) reserved_place_json = reserved_place.serialize() message = f"{reserved_place_json['name']},<br>"\ f"Thank you for your reservation of {reserved_place_json['event_title']} "\ f"on {reserved_place_json['nice_event_date']}" message_html = get_email_html(BASIC, message=message) send_email(data['email'], f"Reserved place for: {reserved_place_json['event_title']}", message_html) return jsonify(reserved_place_json)
def it_shows_divider_error(self, mocker, db_session, sample_magazine, topics): mock_render_template = mocker.patch('app.comms.email.render_template') sample_magazine.topics = topics get_email_html(MAGAZINE, magazine_id=sample_magazine.id) args, kwargs = mock_render_template.call_args assert args[0] == 'emails/magazine.html' assert kwargs['topics'] == [{ 'description': 'Use : as divider between topic header and sub-header', 'title': 'Missing divider' }, { 'description': topics, 'title': 'Topics' }]
def subscribe_member(): data = request.get_json(force=True) current_app.logger.info('Subscribe member: {}'.format(data)) validate(data, post_subscribe_member_schema) member = dao_get_member_by_email(data.get('email')) if member: return jsonify( {'error': 'member already subscribed: {}'.format(member.email)}), 400 member = Member(name=data['name'], email=data['email'], marketing_id=data['marketing_id'], active=True) dao_create_member(member) send_ga_event(f"Subscribed {member.id}", "members", "subscribe", f"{member.id}") basic_html = get_email_html( email_type=BASIC, title='Subscription', message= "Thank you{} for subscribing to New Acropolis events and magazines". format(' {}'.format(data.get('name', '')) if 'name' in data else ''), member_id=member.id) response = send_email(data['email'], 'New Acropolis subscription', basic_html) return jsonify(member.serialize())
def send_emails(email_id): members_not_sent_to = dao_get_members_not_sent_to(email_id) if current_app.config['ENVIRONMENT'] != 'live': limit = 3 current_app.logger.info('Task send_emails received %s, sending %d emails', email_id, limit or len(members_not_sent_to)) email = dao_get_email_by_id(email_id) for index, (member_id, email_to) in enumerate(members_not_sent_to): if limit and index > limit - 1: break subject = email.get_subject() message = None if email.email_type == EVENT: message = get_email_html(email.email_type, event_id=email.event_id, details=email.details, extra_txt=email.extra_txt, member_id=member_id) email_status_code = send_email(email_to, subject, message) dao_add_member_sent_to_email(email_id, member_id, status_code=email_status_code)
def email_preview(): data = json.loads(unquote(request.args.get('data'))) validate(data, post_preview_email_schema) current_app.logger.info('Email preview: {}'.format(data)) html = get_email_html(**data) return html
def it_gets_list_of_topics_for_magazine_emails(self, mocker, db_session, sample_magazine): mock_render_template = mocker.patch('app.comms.email.render_template') sample_magazine.topics = "Philosophy: test 1\nCulture: test 2\nArt: test 3" get_email_html(MAGAZINE, magazine_id=sample_magazine.id) args, kwargs = mock_render_template.call_args assert args[0] == 'emails/magazine.html' assert kwargs['topics'] == [{ 'description': ' test 1', 'title': 'Philosophy' }, { 'description': ' test 2', 'title': 'Culture' }, { 'description': ' test 3', 'title': 'Art' }]
def send_emails(email_id): members_not_sent_to = dao_get_members_not_sent_to(email_id) current_app.logger.info('Task send_emails received %s, sending %d emails', email_id, len(members_not_sent_to)) email = dao_get_email_by_id(email_id) for member_id, email_to in members_not_sent_to: subject = email.get_subject() message = None if email.email_type == EVENT: message = get_email_html( email.email_type, event_id=email.event_id, details=email.details, extra_txt=email.extra_txt) email_status_code = send_email(email_to, subject, message) dao_add_member_sent_to_email(email_id, member_id, status_code=email_status_code)
def unsubscribe_member(unsubcode): member = _get_member_from_unsubcode(unsubcode) dao_update_member(member.id, active=False) send_ga_event(f"Unsubscribed {member.id}", "members", "unsubscribe", f"{member.id}") basic_html = get_email_html( email_type=BASIC, title='Unsubscribe', message= "{}, you have successfully unsubscribed from New Acropolis events and magazines" .format(member.name)) send_email(member.email, 'New Acropolis unsubscription', basic_html) return jsonify({'message': '{} unsubscribed'.format(member.name)})
def upload_magazine(magazine_id, pdf_data): current_app.logger.info('Upload magazine pdf: {}'.format(magazine_id)) try: magazine = dao_get_magazine_by_id(magazine_id) storage = Storage(current_app.config['STORAGE']) decoded_data = base64.b64decode(pdf_data) storage.upload_blob_from_base64string(magazine.filename, magazine.filename, decoded_data, content_type='application/pdf') try: topics = extract_topics(base64.b64decode(decoded_data)) except Exception as e: topics = [] current_app.logger.error("Error extracting topics: %r", e) dao_update_record(Magazine, magazine_id, topics=topics) email = dao_get_email_by_magazine_id(magazine_id) if not email: email = Email(magazine_id=magazine.id, email_state=READY, email_type=MAGAZINE) dao_create_email(email) emails_to = [user.email for user in dao_get_users()] subject = 'Please review {}'.format(magazine.title) # send email to admin users and ask them to log in in order to approve the email review_part = '<div>Please review this email: {}/emails/{}</div>'.format( current_app.config['FRONTEND_ADMIN_URL'], str(email.id)) magazine_html = get_email_html(MAGAZINE, magazine_id=magazine.id) response = send_smtp_email(emails_to, subject, review_part + magazine_html) if response != 200: current_app.logger.error( 'Error sending review email {}, for {}'.format( email.id, magazine.id)) except Exception as e: current_app.logger.error('Task error uploading magazine: {}'.format( str(e)))
def send_event_email_reminder(): current_app.logger.info('Task send_event_email_reminder received: {}') for event in dao_get_future_events(): if event.event_state != APPROVED: continue event.event_dates.sort(key=lambda k: k.event_datetime) time_to_send = (event.event_dates[0].event_datetime - timedelta(weeks=2)) < datetime.today() if time_to_send and not dao_get_email_by_event_id(event.id): subject = f"Event: {event.title} email reminder" message = f"Please <a href='{current_app.config['FRONTEND_ADMIN_URL']}/emails'>"\ f"login</a> to create an email for {event.title}" message_html = get_email_html(BASIC, message=message) for user in dao_get_admin_users(): status_code = send_smtp_email(user.email, subject, message_html) if status_code != 200: current_app.logger.error( f"Problem sending reminder email {subject} for {user.id}, status code: {status_code}")
def update_email(email_id): data = request.get_json(force=True) validate(data, post_update_email_schema) if data['email_type'] == EVENT: try: event = dao_get_event_by_id(data.get('event_id')) except NoResultFound: raise InvalidRequest( 'event not found: {}'.format(data.get('event_id')), 400) email_data = {} for k in data.keys(): if hasattr(Email, k): email_data[k] = data[k] current_app.logger.info('Update email: {}'.format(email_data)) res = dao_update_email(email_id, **email_data) if res: email = dao_get_email_by_id(email_id) response = None emails_to = [user.email for user in dao_get_users()] if data.get('email_state') == READY: # send email to admin users and ask them to log in in order to approve the email review_part = '<div>Please review this email: {}/emails/{}</div>'.format( current_app.config['FRONTEND_ADMIN_URL'], str(email.id)) subject = None if email.email_type == EVENT: event = dao_get_event_by_id(email.event_id) subject = 'Please review {}'.format(event.title) event_html = get_email_html(**data) response = send_smtp_email(emails_to, subject, review_part + event_html) elif email.email_type == MAGAZINE: magazine = dao_get_magazine_by_id(email.magazine_id) subject = 'Please review {}'.format(magazine.title) magazine_html = get_email_html(MAGAZINE, magazine_id=magazine.id) response = send_smtp_email(emails_to, subject, review_part + magazine_html) elif data.get('email_state') == REJECTED: dao_update_email(email_id, email_state=REJECTED) message = '<div>Please correct this email <a href="{}">{}</a></div>'.format( '{}/emails/{}'.format(current_app.config['FRONTEND_ADMIN_URL'], str(email.id)), email.get_subject()) message += '<div>Reason: {}</div>'.format( data.get('reject_reason')) response = send_smtp_email( emails_to, '{} email needs to be corrected'.format(event.title), message) elif data.get('email_state') == APPROVED: later = datetime.utcnow() + timedelta( hours=current_app.config['EMAIL_DELAY']) if later < email.send_starts_at: later = email.send_starts_at + timedelta(hours=9) dao_update_email(email_id, send_after=later) review_part = '<div>Email will be sent after {}, log in to reject: {}/emails/{}</div>'.format( later.strftime("%d/%m/%Y %H:%M"), current_app.config['FRONTEND_ADMIN_URL'], str(email.id)) if email.email_type == EVENT: event_html = get_email_html(**data) response = send_smtp_email( emails_to, "{} has been approved".format(email.get_subject()), review_part + event_html) email_json = email.serialize() if response: email_json['email_status_code'] = response return jsonify(email_json), 200 raise InvalidRequest('{} did not update email'.format(email_id), 400)
def update_email(email_id): data = request.get_json(force=True) validate(data, post_update_email_schema) if data['email_type'] == EVENT: try: event = dao_get_event_by_id(data.get('event_id')) except NoResultFound: raise InvalidRequest('event not found: {}'.format(data.get('event_id')), 400) email_data = {} for k in data.keys(): if hasattr(Email, k): email_data[k] = data[k] current_app.logger.info('Update email: {}'.format(email_data)) res = dao_update_email(email_id, **email_data) if res: email = dao_get_email_by_id(email_id) response = None emails_to = [user.email for user in dao_get_users()] if data.get('email_state') == READY: subject = None if data['email_type'] == EVENT: event = dao_get_event_by_id(data.get('event_id')) subject = 'Please review {}'.format(event.title) # send email to admin users and ask them to log in in order to approve the email review_part = '<div>Please review this email: {}/emails/{}</div>'.format( current_app.config['FRONTEND_ADMIN_URL'], str(email.id)) event_html = get_email_html(**data) response = send_email(emails_to, subject, review_part + event_html) elif data.get('email_state') == REJECTED: if email.task_id: revoke_task(email.task_id) message = '<div>Please correct this email <a href="{}">{}</a></div>'.format( '{}/emails/{}'.format(current_app.config['FRONTEND_ADMIN_URL'], str(email.id)), email.get_subject()) message += '<div>Reason: {}</div>'.format(data.get('reject_reason')) response = send_email(emails_to, '{} email needs to be corrected'.format(event.title), message) elif data.get('email_state') == APPROVED: # send the email later in order to allow it to be rejected later = datetime.utcnow() + timedelta(seconds=current_app.config['EMAIL_DELAY']) if later < email.send_starts_at: later = email.send_starts_at + timedelta(hours=9) result = email_tasks.send_emails.apply_async(((str(email_id)),), eta=later) dao_update_email(email_id, task_id=result.id) current_app.logger.info('Task: send_email: %d, %r at %r', email_id, result.id, later) review_part = '<div>Email will be sent at {}, log in to reject: {}/emails/{}</div>'.format( later, current_app.config['FRONTEND_ADMIN_URL'], str(email.id)) event_html = get_email_html(**data) response = send_email( emails_to, "{} has been approved".format(email.get_subject()), review_part + event_html) email_json = email.serialize() if response: email_json['email_status_code'] = response return jsonify(email_json), 200 raise InvalidRequest('{} did not update email'.format(email_id), 400)