Repository: fossasia/open-event-server

Issue:
Add an end point for resending the verification mail to the user.
**Is your feature request related to a problem? Please describe.**
<!-- A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] -->
Currently, when the user registers, a confirmation mail is sent out. However if the link expires or the mail gets deleted, there should be an option for the user to make the server resend a verification mail.

**Describe the solution you'd like**
<!-- A clear and concise description of what you want to happen. -->
![image](https://user-images.githubusercontent.com/17252805/41915878-0fb96b66-7957-11e8-9294-9ff5531bc9aa.png)
Currently the link on the FE doesn't work, because there is no proper support for that.


Discussion:
I would like to implement this.

On Tue, Jun 26, 2018 at 7:10 PM, Abhinav Khare <notifications@github.com>
wrote:

> *Is your feature request related to a problem? Please describe.*
>
> Currently, when the user registers, a confirmation mail is sent out.
> However if the link expires or the mail gets deleted, there should be an
> option for the user to make the server resend a verification mail.
> *Describe the solution you'd like*
>
> [image: image]
> <https://user-images.githubusercontent.com/17252805/41915878-0fb96b66-7957-11e8-9294-9ff5531bc9aa.png>
> Currently the link on the FE doesn't work, because there is no proper
> support for that.
>
> —
> You are receiving this because you are subscribed to this thread.
> Reply to this email directly, view it on GitHub
> <https://github.com/fossasia/open-event-server/issues/4968>, or mute the
> thread
> <https://github.com/notifications/unsubscribe-auth/AVwOaH6t_PXp2Lt2pagC8FFNixar7Njfks5uAjm7gaJpZM4U39rf>
> .
>


Resolving patch:
diff --git a/app/api/auth.py b/app/api/auth.py
--- a/app/api/auth.py
+++ b/app/api/auth.py
@@ -6,11 +6,13 @@
 from app import get_settings
 from app.api.helpers.db import save_to_db
 from app.api.helpers.files import make_frontend_url
-from app.api.helpers.mail import send_email_with_action
+from app.api.helpers.mail import send_email_with_action, \
+                                 send_email_confirmation
 from app.api.helpers.notification import send_notification_with_action
 
-from app.api.helpers.utilities import get_serializer
-from app.models.mail import PASSWORD_RESET, PASSWORD_CHANGE
+from app.api.helpers.utilities import get_serializer, str_generator
+from app.models.mail import PASSWORD_RESET, PASSWORD_CHANGE, \
+                            USER_REGISTER_WITH_PASSWORD
 from app.models.notification import PASSWORD_CHANGE as PASSWORD_CHANGE_NOTIF
 from app.models.user import User
 from app.api.helpers.errors import UnprocessableEntityError, NotFoundError, BadRequestError
@@ -38,6 +40,32 @@ def verify_email():
         return make_response(jsonify(message="Email Verified"), 200)
 
 
+@auth_routes.route('/resend-verification-email', methods=['POST'])
+def resend_verification_email():
+    try:
+        email = request.json['data']['email']
+    except TypeError:
+        return BadRequestError({'source': ''}, 'Bad Request Error').respond()
+
+    try:
+        user = User.query.filter_by(email=email).one()
+    except NoResultFound:
+        return UnprocessableEntityError(
+            {'source': ''}, 'User with email: ' + email + ' not found.').respond()
+    else:
+        serializer = get_serializer()
+        hash_ = str(base64.b64encode(str(serializer.dumps(
+            [user.email, str_generator()])).encode()), 'utf-8')
+        link = make_frontend_url(
+            '/email/verify'.format(id=user.id), {'token': hash_})
+        send_email_with_action(
+            user, USER_REGISTER_WITH_PASSWORD,
+            app_name=get_settings()['app_name'], email=user.email)
+        send_email_confirmation(user.email, link)
+
+        return make_response(jsonify(message="Verification email resent"), 200)
+
+
 @auth_routes.route('/reset-password', methods=['POST'])
 def reset_password_post():
     try:
diff --git a/app/api/helpers/mail.py b/app/api/helpers/mail.py
--- a/app/api/helpers/mail.py
+++ b/app/api/helpers/mail.py
@@ -58,11 +58,12 @@ def send_email(to, action, subject, html):
             else:
                 payload['fromname'] = email_from_name
                 key = get_settings()['sendgrid_key']
-                if not key and not current_app.config['TESTING']:
+                if not key:
                     print('Sendgrid key not defined')
                     return
                 headers = {
-                    "Authorization": ("Bearer " + key)
+                    "Authorization": ("Bearer " + key),
+                    "Content-Type": "application/json"
                 }
                 from .tasks import send_email_task
                 send_email_task.delay(payload, headers)
diff --git a/app/api/helpers/tasks.py b/app/api/helpers/tasks.py
--- a/app/api/helpers/tasks.py
+++ b/app/api/helpers/tasks.py
@@ -1,7 +1,9 @@
+import csv
+import json
 import os
 import requests
 import uuid
-import csv
+
 from flask import current_app, render_template
 from marrow.mailer import Mailer, Message
 
@@ -41,10 +43,16 @@
 
 @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"]}]
     requests.post(
-        "https://api.sendgrid.com/api/mail.send.json",
-        data=payload,
-        headers=headers
+        "https://api.sendgrid.com/v3/mail/send",
+        data=json.dumps(data),
+        headers=headers,
+        verify=False  # doesn't work with verification in celery context
     )
 
 


Test patch: