diff --git a/app/api/helpers/mail.py b/app/api/helpers/mail.py
index 1ba0835982..80daea666b 100644
--- a/app/api/helpers/mail.py
+++ b/app/api/helpers/mail.py
@@ -15,7 +15,7 @@
from app.models.user import User
-def send_email(to, action, subject, html):
+def send_email(to, action, subject, html, attachments=None):
"""
Sends email and records it in DB
"""
@@ -30,7 +30,8 @@ def send_email(to, action, subject, html):
'to': to,
'from': email_from,
'subject': subject,
- 'html': html
+ 'html': html,
+ 'attachments': attachments
}
if not current_app.config['TESTING']:
@@ -278,7 +279,8 @@ def send_email_change_user_email(user, email):
send_email_with_action(email, USER_CHANGE_EMAIL, email=email, new_email=user.email)
-def send_email_to_attendees(order, purchaser_id):
+def send_email_to_attendees(order, purchaser_id, attachments=None):
+
for holder in order.ticket_holders:
if holder.user and holder.user.id == purchaser_id:
# Ticket holder is the purchaser
@@ -292,7 +294,8 @@ def send_email_to_attendees(order, purchaser_id):
html=MAILS[TICKET_PURCHASED]['message'].format(
pdf_url=holder.pdf_url,
event_name=order.event.name
- )
+ ),
+ attachments=attachments
)
else:
# The Ticket holder is not the purchaser
@@ -306,7 +309,8 @@ def send_email_to_attendees(order, purchaser_id):
html=MAILS[TICKET_PURCHASED_ATTENDEE]['message'].format(
pdf_url=holder.pdf_url,
event_name=order.event.name
- )
+ ),
+ attachments=attachments
)
diff --git a/app/api/helpers/system_mails.py b/app/api/helpers/system_mails.py
index 3ea3b154c5..8a6d80a50b 100644
--- a/app/api/helpers/system_mails.py
+++ b/app/api/helpers/system_mails.py
@@ -145,7 +145,7 @@
'message': (
u"Hi, this is a confirmation mail of your tickets for the event {event_name}"
u"
Your order has been processed successfully." +
- u"
Click here to view/download your invoice."
+ u"
You can find your Tickets and Order Invoice attached to this mail."
u"
Looking forward to seeing you at the event."
u"
Login to manage your orders at https://eventyay.com "
)
diff --git a/app/api/helpers/tasks.py b/app/api/helpers/tasks.py
index 3ddcf9b703..002a581dad 100644
--- a/app/api/helpers/tasks.py
+++ b/app/api/helpers/tasks.py
@@ -6,6 +6,11 @@
from flask import current_app, render_template
from marrow.mailer import Mailer, Message
+from app import get_settings
+from sendgrid import SendGridAPIClient
+from sendgrid.helpers.mail import (
+ Mail, Attachment, FileContent, FileName,
+ FileType, Disposition)
from app import make_celery
from app.api.helpers.utilities import strip_tags
@@ -41,25 +46,33 @@
from app.api.helpers.db import save_to_db
from app.api.helpers.files import create_save_pdf
import urllib.error
+import base64
celery = make_celery()
@celery.task(name='send.email.post')
def send_email_task(payload, headers):
- data = {"personalizations": [{"to": []}]}
- data["personalizations"][0]["to"].append({"email": payload["to"]})
- data["from"] = {"email": payload["from"]}
- data["subject"] = payload["subject"]
- data["content"] = [{"type": "text/html", "value": payload["html"]}]
- logging.info('Sending an email regarding {} on behalf of {}'.format(data["subject"], data["from"]))
+ message = Mail(from_email=payload['from'],
+ to_emails=payload['to'],
+ subject=payload['subject'],
+ html_content=payload["html"])
+ if payload['attachments'] is not None:
+ for attachment in payload['attachments']:
+ with open(attachment, 'rb') as f:
+ file_data = f.read()
+ f.close()
+ encoded = base64.b64encode(file_data).decode()
+ attachment = Attachment()
+ attachment.file_content = FileContent(encoded)
+ attachment.file_type = FileType('application/pdf')
+ attachment.file_name = FileName(payload['to'])
+ attachment.disposition = Disposition('attachment')
+ message.add_attachment(attachment)
+ sendgrid_client = SendGridAPIClient(get_settings()['sendgrid_key'])
+ logging.info('Sending an email regarding {} on behalf of {}'.format(payload["subject"], payload["from"]))
try:
- requests.post(
- "https://api.sendgrid.com/v3/mail/send",
- data=json.dumps(data),
- headers=headers,
- verify=False # doesn't work with verification in celery context
- )
+ sendgrid_client.send(message)
logging.info('Email sent successfully')
except Exception:
logging.exception('Error occured while sending the email')
@@ -84,6 +97,7 @@ def send_mail_via_smtp_task(config, payload):
message.subject = payload['subject']
message.plain = strip_tags(payload['html'])
message.rich = payload['html']
+ message.attach(name=payload['attachments'])
mailer.send(message)
logging.info('Message sent via SMTP')
mailer.stop()
diff --git a/app/api/orders.py b/app/api/orders.py
index bcfafa0b80..096fd2285b 100644
--- a/app/api/orders.py
+++ b/app/api/orders.py
@@ -10,6 +10,7 @@
from app.api.bootstrap import api
from app.api.data_layers.ChargesLayer import ChargesLayer
from app.api.helpers.db import save_to_db, safe_query, safe_query_without_soft_deleted_entries
+from app.api.helpers.storage import generate_hash, UPLOAD_PATHS
from app.api.helpers.errors import BadRequestError
from app.api.helpers.exceptions import ForbiddenException, UnprocessableEntity, ConflictException
from app.api.helpers.files import make_frontend_url
@@ -139,10 +140,22 @@ def after_create_object(self, order, data, view_kwargs):
# send e-mail and notifications if the order status is completed
if order.status == 'completed':
+ # fetch tickets attachment
+ order_identifier = order.identifier
+
+ key = UPLOAD_PATHS['pdf']['ticket_attendee'].format(identifier=order_identifier)
+ ticket_path = 'generated/tickets/{}/{}/'.format(key, generate_hash(key)) + order_identifier + '.pdf'
+
+ key = UPLOAD_PATHS['pdf']['order'].format(identifier=order_identifier)
+ invoice_path = 'generated/invoices/{}/{}/'.format(key, generate_hash(key)) + order_identifier + '.pdf'
+
+ # send email and notifications.
+ send_email_to_attendees(order=order, purchaser_id=current_user.id, attachments=[ticket_path, invoice_path])
+
+ send_notif_to_attendees(order, current_user.id)
+
if order.payment_mode in ['free', 'bank', 'cheque', 'onsite']:
order.completed_at = datetime.utcnow()
- send_email_to_attendees(order, current_user.id)
- send_notif_to_attendees(order, current_user.id)
order_url = make_frontend_url(path='/orders/{identifier}'.format(identifier=order.identifier))
for organizer in order.event.organizers:
@@ -310,10 +323,23 @@ def after_update_object(self, order, data, view_kwargs):
delete_related_attendees_for_order(order)
elif order.status == 'completed':
+
+ # Send email to attendees with invoices and tickets attached
+ order_identifier = order.identifier
+
+ key = UPLOAD_PATHS['pdf']['ticket_attendee'].format(identifier=order_identifier)
+ ticket_path = 'generated/tickets/{}/{}/'.format(key, generate_hash(key)) + order_identifier + '.pdf'
+
+ key = UPLOAD_PATHS['pdf']['order'].format(identifier=order_identifier)
+ invoice_path = 'generated/invoices/{}/{}/'.format(key, generate_hash(key)) + order_identifier + '.pdf'
+
+ # send email and notifications.
+ send_email_to_attendees(order=order, purchaser_id=current_user.id, attachments=[ticket_path, invoice_path])
+
+ send_notif_to_attendees(order, current_user.id)
+
if order.payment_mode in ['free', 'bank', 'cheque', 'onsite']:
order.completed_at = datetime.utcnow()
- send_email_to_attendees(order, current_user.id)
- send_notif_to_attendees(order, current_user.id)
order_url = make_frontend_url(path='/orders/{identifier}'.format(identifier=order.identifier))
for organizer in order.event.organizers:
diff --git a/requirements/common.txt b/requirements/common.txt
index 4814154381..d8863a27e9 100644
--- a/requirements/common.txt
+++ b/requirements/common.txt
@@ -17,6 +17,7 @@ celery>=3.1.23,<4
redis>=2.10.5,<3
apscheduler>=3.3.0,<4
pillow
+sendgrid>=6.0.5
amqp<2.0,>=1.4.9
gunicorn>=19.6.0,<20
boto>=2.45.0,<3