Exemple #1
0
def users():
    form = NewUserForm()

    if form.validate_on_submit():
        email, name = form.email.data, form.name.data
        user = User(email, name)

        db.session.add(user)
        db.session.commit()
        app.logger.info(
            "%s manually created new user with email %s and id: %s",
            current_user.id,
            email,
            user.id,
        )

        code = user.login_code(app.config["SECRET_KEY"])
        msg = EmailMessage(
            "Welcome to the EMF website",
            from_email=from_email("CONTACT_EMAIL"),
            to=[email],
        )
        msg.body = render_template("emails/manually-added-user.txt",
                                   user=user,
                                   code=code)
        msg.send()

        flash("Created account for: %s" % name)
        return redirect(url_for(".users"))

    users = User.query.order_by(User.id).options(joinedload(
        User.permissions)).all()
    return render_template("admin/users/users.html", users=users, form=form)
Exemple #2
0
def stripe_payment_paid(payment: StripePayment):
    if payment.state == "paid":
        logger.info("Payment is already paid, ignoring")
        return

    if payment.state == "partrefunded":
        logger.info("Payment is already partially refunded, ignoring")
        return

    logger.info("Setting payment %s to paid", payment.id)
    payment.paid()
    db.session.commit()

    msg = EmailMessage(
        "Your EMF payment has been confirmed",
        from_email=from_email("TICKETS_EMAIL"),
        to=[payment.user.email],
    )

    already_emailed = set_tickets_emailed(payment.user)
    msg.body = render_template(
        "emails/tickets-paid-email-stripe.txt",
        user=payment.user,
        payment=payment,
        already_emailed=already_emailed,
    )

    if feature_enabled("ISSUE_TICKETS"):
        attach_tickets(msg, payment.user)

    msg.send()
    db.session.commit()
Exemple #3
0
def email_tickets():
    """Email tickets to those who haven't received them"""
    users_purchase_counts = (Purchase.query.filter_by(
        is_paid_for=True,
        state="paid").join(PriceTier, Product, ProductGroup).filter(
            ProductGroup.type.in_(RECEIPT_TYPES)).join(
                Purchase.owner).with_entities(User, func.count(
                    Purchase.id)).group_by(User).order_by(User.id))

    for user, purchase_count in users_purchase_counts:
        plural = purchase_count != 1 and "s" or ""

        msg = EmailMessage(
            "Your Electromagnetic Field Ticket%s" % plural,
            from_email=from_email("TICKETS_EMAIL"),
            to=[user.email],
        )

        already_emailed = set_tickets_emailed(user)
        msg.body = render_template("emails/receipt.txt",
                                   user=user,
                                   already_emailed=already_emailed)

        attach_tickets(msg, user)

        app.logger.info("Emailing %s receipt for %s tickets", user.email,
                        purchase_count)
        msg.send()

        db.session.commit()
 def test_dummy_backend(self):
     self.app.extensions['mailman'].backend = 'dummy'
     msg = EmailMessage(
         subject="testing",
         to=["*****@*****.**"],
         body="testing",
     )
     assert msg.send() == 1
Exemple #5
0
def transaction_reconcile(txn_id, payment_id):
    txn = BankTransaction.query.get_or_404(txn_id)
    payment = BankPayment.query.get_or_404(payment_id)

    form = ManualReconcilePaymentForm()
    if form.validate_on_submit():
        if form.reconcile.data:
            app.logger.info(
                "%s manually reconciling against payment %s (%s) by %s",
                current_user.name,
                payment.id,
                payment.bankref,
                payment.user.email,
            )

            if txn.payment:
                app.logger.error("Transaction already reconciled")
                flash("Transaction %s already reconciled" % txn.id)
                return redirect(url_for("admin.transactions"))

            payment.lock()

            if payment.state == "paid":
                app.logger.error("Payment has already been paid")
                flash("Payment %s already paid" % payment.id)
                return redirect(url_for("admin.transactions"))

            txn.payment = payment
            payment.paid()
            db.session.commit()

            msg = EmailMessage(
                "Electromagnetic Field ticket purchase update",
                from_email=from_email("TICKETS_EMAIL"),
                to=[payment.user.email],
            )

            already_emailed = set_tickets_emailed(payment.user)
            msg.body = render_template(
                "emails/tickets-paid-email-banktransfer.txt",
                user=payment.user,
                payment=payment,
                already_emailed=already_emailed,
            )

            if feature_enabled("ISSUE_TICKETS"):
                attach_tickets(msg, payment.user)

            msg.send()

            flash("Payment ID %s marked as paid" % payment.id)
            return redirect(url_for("admin.transactions"))

    return render_template("admin/accounts/txn-reconcile.html",
                           txn=txn,
                           payment=payment,
                           form=form)
Exemple #6
0
 def test_send_without_sender(self):
     self.app.extensions['mailman'].default_sender = None
     msg = EmailMessage(subject="testing",
                        to=["*****@*****.**"],
                        body="testing")
     msg.send()
     self.assertEqual(len(self.mail.outbox), 1)
     sent_msg = self.mail.outbox[0]
     self.assertEqual(sent_msg.from_email, None)
Exemple #7
0
def handle_free_tickets(flow: str, view: ProductView, basket: Basket):
    """The user is trying to "buy" only free tickets.

    This is effectively a payment stage, handled differently
    from the rest of the flow.
    """
    # They must be authenticated for this.
    if not current_user.is_authenticated:
        app.logger.warn("User is not authenticated, sending to login")
        flash("You must be logged in to buy additional free tickets")
        return redirect(
            url_for("users.login", next=url_for("tickets.main", flow=flow)))

    # We sell under-12 tickets to non-CfP users, to enforce capacity.
    # We don't let people order an under-12 ticket on its own.
    # However, CfP users need to be able to buy day and parking tickets.
    admissions_tickets = current_user.get_owned_tickets(
        type="admission_ticket")
    if not any(admissions_tickets) and not view.cfp_accepted_only:
        app.logger.warn(
            "User trying to buy free add-ons without an admission ticket")
        flash(
            "You must have an admissions ticket to buy additional free tickets"
        )
        return redirect(url_for("tickets.main", flow=flow))

    basket.user = current_user
    basket.check_out_free()
    db.session.commit()

    Basket.clear_from_session()

    msg = EmailMessage(
        "Your EMF ticket order",
        from_email=from_email("TICKETS_EMAIL"),
        to=[current_user.email],
    )

    already_emailed = set_tickets_emailed(current_user)
    msg.body = render_template(
        "emails/tickets-ordered-email-free.txt",
        user=current_user,
        basket=basket,
        already_emailed=already_emailed,
    )
    if feature_enabled("ISSUE_TICKETS"):
        attach_tickets(msg, current_user)

    msg.send()

    if len(basket.purchases) == 1:
        flash("Your ticket has been confirmed")
    else:
        flash("Your tickets have been confirmed")

    return redirect(url_for("users.purchases"))
Exemple #8
0
 def test_send_message(self):
     msg = EmailMessage(
         subject="testing",
         to=["*****@*****.**"],
         body="testing",
     )
     msg.send()
     self.assertEqual(len(self.mail.outbox), 1)
     sent_msg = self.mail.outbox[0]
     self.assertEqual(sent_msg.from_email,
                      self.app.extensions["mailman"].default_sender)
    def test_invalid_backend(self):
        self.app.extensions['mailman'].backend = 'unknown'
        msg = EmailMessage(
            subject="testing",
            to=["*****@*****.**"],
            body="testing",
        )

        with pytest.raises(RuntimeError) as exc:
            msg.send()
        assert "The available built-in mail backends" in str(exc)
Exemple #10
0
    def test_smtp_backend(self):
        self.app.extensions['mailman'].backend = 'smtp'
        msg = EmailMessage(
            subject="testing",
            to=["*****@*****.**"],
            body="testing",
        )

        with patch.object(smtp.EmailBackend, 'send_messages') as mock_send_fn:
            mock_send_fn.return_value = 66
            assert msg.send() == 66
Exemple #11
0
    def test_override_custom_backend(self):
        self.app.extensions['mailman'].backend = 'console'
        with self.mail.get_connection(backend=locmem.EmailBackend) as conn:
            msg = EmailMessage(subject="testing",
                               to=["*****@*****.**"],
                               body="testing",
                               connection=conn)
            msg.send()

        self.assertEqual(len(self.mail.outbox), 1)
        sent_msg = self.mail.outbox[0]
        self.assertEqual(sent_msg.subject, "testing")
Exemple #12
0
    def test_console_backend(self):
        self.app.extensions['mailman'].backend = 'console'
        msg = EmailMessage(
            subject="testing",
            to=["*****@*****.**"],
            body="testing",
        )
        msg.send()

        captured = self.capsys.readouterr()
        assert "testing" in captured.out
        assert "To: [email protected]" in captured.out
Exemple #13
0
def ticket_admin_email(title, template, **kwargs):
    if not app.config.get("TICKETS_NOTICE_EMAIL"):
        app.logger.warning("No tickets notice email configured, not sending")
        return

    msg = EmailMessage(
        title,
        from_email=from_email("TICKETS_EMAIL"),
        to=[app.config["TICKETS_NOTICE_EMAIL"][1]],
    )
    msg.body = render_template(template, **kwargs)
    msg.send()
Exemple #14
0
def signup():
    if not request.args.get("code"):
        abort(404)

    uid = verify_signup_code(app.config["SECRET_KEY"], time.time(),
                             request.args.get("code"))
    if uid is None:
        flash(
            "Your signup link was invalid. Please note that they expire after 6 hours."
        )
        abort(404)

    user = User.query.get_or_404(uid)
    if not user.has_permission("admin"):
        app.logger.warn("Signup link resolves to non-admin user %s", user)
        abort(404)

    form = SignupForm()

    if current_user.is_authenticated:
        return redirect(url_for(".account"))

    if form.validate_on_submit():
        email, name = form.email.data, form.name.data
        user = User(email, name)

        if form.allow_promo.data:
            user.promo_opt_in = True

        db.session.add(user)
        db.session.commit()
        app.logger.info("Signed up new user with email %s and id %s", email,
                        user.id)

        msg = EmailMessage(
            "Welcome to the EMF website",
            from_email=from_email("CONTACT_EMAIL"),
            to=[email],
        )
        msg.body = render_template("emails/signup-user.txt", user=user)
        msg.send()

        login_user(user)

        return redirect(url_for(".account"))

    if request.args.get("email"):
        form.email.data = request.args.get("email")

    return render_template("account/signup.html", form=form)
Exemple #15
0
    def test_locmem_backend(self):
        self.app.extensions['mailman'].backend = 'locmem'
        msg = EmailMessage(
            subject="testing",
            to=["*****@*****.**"],
            body="testing",
        )
        msg.send()

        self.assertEqual(len(self.mail.outbox), 1)
        sent_msg = self.mail.outbox[0]
        self.assertEqual(sent_msg.subject, "testing")
        self.assertEqual(sent_msg.to, ["*****@*****.**"])
        self.assertEqual(sent_msg.body, "testing")
        self.assertEqual(sent_msg.from_email,
                         self.app.extensions["mailman"].default_sender)
Exemple #16
0
    def test_filebased_backend(self):
        with tempfile.TemporaryDirectory() as tempdir:
            self.app.extensions['mailman'].backend = 'file'
            self.app.extensions['mailman'].file_path = tempdir
            with self.mail.get_connection() as conn:
                msg = EmailMessage(
                    subject="testing",
                    to=["*****@*****.**"],
                    body="testing",
                    connection=conn,
                )
                msg.send()

            wrote_file = Path(conn._fname)
            assert wrote_file.is_file()
            assert "To: [email protected]" in wrote_file.read_text()
Exemple #17
0
def send_refund_email(request: RefundRequest, amount: Decimal) -> None:
    payment = request.payment
    msg = EmailMessage(
        "Your refund request has been processed",
        from_email=from_email("TICKETS_EMAIL"),
        to=[payment.user.email],
    )
    # TODO: handle situation where currency of refund is different from currency of payment.
    msg.body = render_template(
        "emails/refund-sent.txt",
        user=payment.user,
        amount=amount,
        request=request,
        currency=payment.currency,
    )
    msg.send()
Exemple #18
0
 def test_send_single(self):
     with self.mail.get_connection() as conn:
         msg = EmailMessage(
             subject="testing",
             to=["*****@*****.**"],
             body="testing",
             connection=conn,
         )
         msg.send()
         self.assertEqual(len(self.mail.outbox), 1)
         sent_msg = self.mail.outbox[0]
         self.assertEqual(sent_msg.subject, "testing")
         self.assertEqual(sent_msg.to, ["*****@*****.**"])
         self.assertEqual(sent_msg.body, "testing")
         self.assertEqual(sent_msg.from_email,
                          self.app.extensions["mailman"].default_sender)
def send_email(subject, body, send_to):

    try:

        msg = EmailMessage(subject, body, Config.MAIL_USERNAME, [send_to])
        msg.content_subtype = "html"
        msg.send()

        return True

    except:
        current_app.logger.info(
            'ERR - Cannot send email, please check MAIL settings')
        current_app.logger.info('    -> MAIL Subject: ' + subject)
        current_app.logger.info('    -> MAIL Body: ' + body)
        return False
Exemple #20
0
def send_reminder(payment_id):
    payment = BankPayment.query.get_or_404(payment_id)

    form = SendReminderForm()
    if form.validate_on_submit():
        if form.remind.data:
            app.logger.info(
                "%s sending reminder email to %s <%s> for payment %s",
                current_user.name,
                payment.user.name,
                payment.user.email,
                payment.id,
            )

            payment.lock()

            if payment.reminder_sent_at:
                app.logger.error("Reminder for payment %s already sent",
                                 payment.id)
                flash("Cannot send duplicate reminder email for payment %s" %
                      payment.id)
                return redirect(url_for("admin.expiring"))

            msg = EmailMessage(
                "Electromagnetic Field: Your tickets will expire in five days",
                from_email=from_email("TICKETS_EMAIL"),
                to=[payment.user.email],
            )
            msg.body = render_template(
                "emails/tickets-reminder.txt",
                payment=payment,
                account=payment.recommended_destination,
            )
            msg.send()

            payment.reminder_sent_at = datetime.utcnow()
            db.session.commit()

            flash("Reminder email for payment %s sent" % payment.id)
            return redirect(url_for("admin.expiring"))

    return render_template(
        "admin/payments/payment-send-reminder.html",
        payment=payment,
        account=payment.recommended_destination,
        form=form,
    )
Exemple #21
0
def login():
    if current_user.is_authenticated:
        return redirect(get_next_url())

    if request.args.get("code"):
        user = User.get_by_code(app.config["SECRET_KEY"],
                                request.args.get("code"))
        if user is not None:
            login_user(user)
            session.permanent = True
            return redirect(get_next_url())
        else:
            flash(
                "Your login link was invalid. Please enter your email address below to receive a new link."
            )

    form = LoginForm(request.form)
    if form.validate_on_submit():
        code = form._user.login_code(app.config["SECRET_KEY"])

        msg = EmailMessage(
            "Electromagnetic Field: Login details",
            from_email=from_email("TICKETS_EMAIL"),
            to=[form._user.email],
        )
        msg.body = render_template(
            "emails/login-code.txt",
            user=form._user,
            code=code,
            next_url=get_next_url(),
        )
        msg.send()

        flash("We've sent you an email with your login link")

    if request.args.get("email"):
        form.email.data = request.args.get("email")

    return render_template(
        "account/login.html",
        form=form,
        next=get_next_url(),
    )
Exemple #22
0
def send_confirmation(payment: BankPayment):
    msg = EmailMessage(
        "Electromagnetic Field ticket purchase update",
        from_email=from_email("TICKETS_EMAIL"),
        to=[payment.user.email],
    )

    already_emailed = set_tickets_emailed(payment.user)
    msg.body = render_template(
        "emails/tickets-paid-email-banktransfer.txt",
        user=payment.user,
        payment=payment,
        already_emailed=already_emailed,
    )

    if feature_enabled("ISSUE_TICKETS"):
        attach_tickets(msg, payment.user)

    msg.send()
    db.session.commit()
Exemple #23
0
def message_proposer(proposal_id):
    form = SendMessageForm()
    proposal = Proposal.query.get_or_404(proposal_id)

    if form.validate_on_submit():
        if form.send.data:
            msg = CFPMessage()
            msg.is_to_admin = False
            msg.from_user_id = current_user.id
            msg.proposal_id = proposal_id
            msg.message = form.message.data

            db.session.add(msg)
            db.session.commit()

            app.logger.info(
                "Sending message from %s to %s", current_user.id, proposal.user_id
            )

            msg_url = external_url("cfp.proposal_messages", proposal_id=proposal_id)
            msg = EmailMessage(
                "New message about your EMF proposal",
                from_email=from_email("CONTENT_EMAIL"),
                to=[proposal.user.email],
            )
            msg.body = render_template(
                "cfp_review/email/new_message.txt",
                url=msg_url,
                to_user=proposal.user,
                from_user=current_user,
                proposal=proposal,
            )
            msg.send()

        count = proposal.mark_messages_read(current_user)
        db.session.commit()
        app.logger.info(
            "Marked %s messages to admin on proposal %s as read" % (count, proposal.id)
        )

        return redirect(url_for(".message_proposer", proposal_id=proposal_id))

    # Admin can see all messages sent in relation to a proposal
    messages = (
        CFPMessage.query.filter_by(proposal_id=proposal_id).order_by("created").all()
    )

    return render_template(
        "cfp_review/message_proposer.html",
        form=form,
        messages=messages,
        proposal=proposal,
    )
Exemple #24
0
def transfer_start(payment: BankPayment):
    if not feature_enabled("BANK_TRANSFER"):
        return redirect(url_for("tickets.pay"))

    if get_user_currency() == "EUR" and not feature_enabled("BANK_TRANSFER_EURO"):
        return redirect(url_for("tickets.pay"))

    logger.info("Created bank payment %s (%s)", payment.id, payment.bankref)

    # No extra preparation required for bank transfer. We can go straight to inprogress.

    if payment.currency == "GBP":
        days = app.config.get("EXPIRY_DAYS_TRANSFER")
    elif payment.currency == "EUR":
        days = app.config.get("EXPIRY_DAYS_TRANSFER_EURO")

    if days is None:
        raise Exception("EXPIRY_DAYS_TRANSFER(_EURO) not set")

    payment.expires = datetime.utcnow() + timedelta(days=days)
    payment.state = "inprogress"

    for purchase in payment.purchases:
        purchase.set_state("payment-pending")

    db.session.commit()

    msg = EmailMessage(
        "Your EMF ticket purchase",
        from_email=from_email("TICKETS_EMAIL"),
        to=[current_user.email],
    )
    msg.body = render_template(
        "emails/tickets-purchased-email-banktransfer.txt",
        user=current_user,
        payment=payment,
    )
    msg.send()

    return redirect(url_for("payments.transfer_waiting", payment_id=payment.id))
Exemple #25
0
 def test_send_many(self):
     with self.mail.get_connection() as conn:
         msgs = []
         for i in range(10):
             msg = EmailMessage(subject="testing",
                                to=["*****@*****.**"],
                                body="testing")
             msgs.append(msg)
         conn.send_messages(msgs)
         self.assertEqual(len(self.mail.outbox), 10)
         sent_msg = self.mail.outbox[0]
         self.assertEqual(sent_msg.from_email,
                          self.app.extensions["mailman"].default_sender)
def test_send_using_helper_function(test_client, flask_app, capfd):
    msg = EmailMessage(
        subject="subject of email",
        body="body of email",
        to=["*****@*****.**"],
        from_email="*****@*****.**",
    )
    _send_email_helper(flask_app, msg)
    captured = capfd.readouterr()

    assert "*****@*****.**" in captured.out
    assert "*****@*****.**" in captured.out
    assert "subject of email" in captured.out
    assert "body of email" in captured.out
Exemple #27
0
def message_batch():
    proposals, filtered = filter_proposal_request()

    form = SendMessageForm()
    if form.validate_on_submit():
        if form.send.data:
            for proposal in proposals:
                msg = CFPMessage()
                msg.is_to_admin = False
                msg.from_user_id = current_user.id
                msg.proposal_id = proposal.id
                msg.message = form.message.data

                db.session.add(msg)
                db.session.commit()

                app.logger.info(
                    "Sending message from %s to %s", current_user.id, proposal.user_id
                )

                msg_url = external_url("cfp.proposal_messages", proposal_id=proposal.id)
                msg = EmailMessage(
                    "New message about your EMF proposal",
                    from_email=from_email("CONTENT_EMAIL"),
                    to=[proposal.user.email],
                )
                msg.body = render_template(
                    "cfp_review/email/new_message.txt",
                    url=msg_url,
                    to_user=proposal.user,
                    from_user=current_user,
                    proposal=proposal,
                )
                msg.send()

            flash("Messaged %s proposals" % len(proposals), "info")
            return redirect(url_for(".proposals", **request.args))

    return render_template(
        "cfp_review/message_batch.html", form=form, proposals=proposals
    )
def background_task(
    channel_url, text, subscribers, subject, mfrom, send_uid, attachments=[]
):
    logger.info(
        'Start send "{subject}" to {subscribers} recipients through channel "{channel}".'.format(  #  noqa
            subject=subject, subscribers=len(subscribers), channel=channel_url
        )
    )
    try:
        with app.mail.get_connection() as conn:
            for i, mto in enumerate(subscribers):
                msg = EmailMessage(
                    from_email=mfrom,
                    to=[mto],
                    body=text,
                    subject=subject,
                    connection=conn,
                )
                msg.content_subtype = "html"
                for attachment in attachments:
                    msg.attach(
                        filename=attachment.get("filename", ""),
                        content=attachment.get("data", ""),
                        mimetype=attachment.get("content_type", ""),
                    )
                try:
                    msg.send()
                except SMTPRecipientsRefused:
                    logger.info("[SKIP] - {}: invalid address.".format(mto))
                if (i + 1) % 1000 == 0:
                    logger.info(
                        "- Sending status: {}/{}".format(i + 1, len(subscribers))
                    )
    except Exception as e:
        logger.error("Message not sent:")
        logger.exception(e)
        send_complete(channel_url=channel_url, send_uid=send_uid, error=True)
        return
    send_complete(channel_url=channel_url, send_uid=send_uid)
    logger.info("Task complete.")
Exemple #29
0
def send_email_for_proposal(proposal, reason="still-considered", from_address=None):
    if reason == "accepted":
        subject = 'Your EMF proposal "%s" has been accepted!' % proposal.title
        template = "cfp_review/email/accepted_msg.txt"

    elif reason == "still-considered":
        subject = 'We\'re still considering your EMF proposal "%s"' % proposal.title
        template = "cfp_review/email/not_accepted_msg.txt"

    elif reason == "rejected":
        proposal.has_rejected_email = True
        subject = 'Your EMF proposal "%s" was not accepted.' % proposal.title
        template = "emails/cfp-rejected.txt"

    elif reason == "check-your-slot":
        subject = (
            "Your EMF proposal '%s' has been scheduled, please check your slot"
            % proposal.title
        )
        template = "emails/cfp-check-your-slot.txt"

    elif reason == "please-finalise":
        subject = "We need information about your EMF proposal '%s'" % proposal.title
        template = "emails/cfp-please-finalise.txt"

    elif reason == "reserve-list":
        subject = "Your EMF proposal '%s', and EMF tickets" % proposal.title
        template = "emails/cfp-reserve-list.txt"

    elif reason == "scheduled":
        subject = "Your EMF %s has been scheduled ('%s')" % (
            proposal.human_type,
            proposal.title,
        )
        template = "emails/cfp-slot-scheduled.txt"

    elif reason == "moved":
        subject = "Your EMF %s slot has been moved ('%s')" % (
            proposal.human_type,
            proposal.title,
        )
        template = "emails/cfp-slot-moved.txt"

    else:
        raise Exception("Unknown cfp proposal email type %s" % reason)

    app.logger.info("Sending %s email for proposal %s", reason, proposal.id)

    send_from = from_email("CONTENT_EMAIL")
    if from_address:
        send_from = from_address

    msg = EmailMessage(subject, from_email=send_from, to=[proposal.user.email])
    msg.body = render_template(
        template,
        user=proposal.user,
        proposal=proposal,
        reserve_ticket_link=app.config["RESERVE_LIST_TICKET_LINK"],
    )

    msg.send()
Exemple #30
0
 def test_bad_header_subject(self):
     msg = EmailMessage(subject="testing\n\r",
                        body="testing",
                        to=["*****@*****.**"])
     with pytest.raises(BadHeaderError):
         msg.send()