def index(): # If we have an access_token, we may interact with the Nylas Server if 'access_token' in session: client = APIClient(APP_ID, APP_SECRET, session['access_token']) message = None while not message: try: # Get the latest message from namespace zero. message = client.messages.first() if not message: # A new account takes a little time to sync print "No messages yet. Checking again in 2 seconds." time.sleep(2) except Exception as e: print(e.message) return Response("<html>An error occurred.</html>") # Format the output text = "<html><h1>Here's a message from your inbox:</h1><b>From:</b> " for sender in message["from"]: text += "{} <{}>".format(sender['name'], sender['email']) text += "<br /><b>Subject:</b> " + message.subject text += "<br /><b>Body:</b> " + message.body text += "</html>" # Return result to the client return Response(text) else: # We don't have an access token, so we're going to use OAuth to # authenticate the user # Ask flask to generate the url corresponding to the login_callback # route. This is similar to using reverse() in django. redirect_uri = url_for('.login_callback', _external=True) client = APIClient(APP_ID, APP_SECRET) return redirect(client.authentication_url(redirect_uri))
def login_callback(): if 'error' in request.args: return "Login error: {0}".format(request.args['error']) client = APIClient(APP_ID, APP_SECRET) code = request.args.get('code') session['access_token'] = client.token_for_code(code) return index()
def login(): if request.endpoint != 'login_callback': if 'access_token' not in session: redirect_uri = url_for('.login_callback', _external=True) client = APIClient(APP_ID, APP_SECRET) return redirect(client.authentication_url(redirect_uri)) else: create_todo_tag()
def login_callback(): if 'error' in request.args: return "Login error: {0}".format(request.args['error']) # Exchange the authorization code for an access token client = APIClient(APP_ID, APP_SECRET) code = request.args.get('code') session['access_token'] = client.token_for_code(code) return redirect(url_for('threads_contacts', offset=0))
def login_callback(): if 'error' in request.args: return "Login error: {0}".format(request.args['error']) # Exchange the authorization code for an access token client = APIClient(APP_ID, APP_SECRET) code = request.args.get('code') token = client.token_for_code(code) return token
def login_callback(): if 'error' in request.args: return "Login error: {0}".format(request.args['error']) # Exchange the authorization code for an access token client = APIClient(APP_ID, APP_SECRET) code = request.args.get('code') session['access_token'] = client.token_for_code(code) return index()
def index(pagenr): session['contact_mails'] = [] session['contact_addresses'] = [] offset = pagenr # If we have an access_token, we may interact with the Nylas Server if 'access_token' in session: client = APIClient(APP_ID, APP_SECRET, session['access_token']) message = None while len(session['contact_addresses']) + 1 < pagenr * 10: try: # Get the latest message from namespace zero. messages = client.messages.where(**{'in': 'all', 'limit': 20, 'offset':offset}) for message in messages: #print message['from'][0]['email'] if message['from'][0]['email'] not in session['contact_addresses']: contact_mail = { 'id': len(session['contact_addresses']), 'date': message['date'], 'name': message['from'][0]['name'], 'email': message['from'][0]['email'], 'snippet': message['snippet'], 'unread': message['unread'] } session['contact_mails'].append(contact_mail) session['contact_addresses'].append(message['from'][0]['email']) #if messages.sender[0]['email'] not in session['emails']: if not messages: # A new account takes a little time to sync print "No messages yet. Checking again in 2 seconds." time.sleep(2) except Exception as e: print(e.message) return Response("<html>An error occurred.</html>") offset += 1 if pagenr - 1 == 0: start = 0 end = 10 else: start = (pagenr - 1) * 10 end = pagenr * 10 response = {'contacts': session['contact_mails'][start:end]} js = json.dumps(response) resp = Response(js, status=200, mimetype='application/json') return resp else: # We don't have an access token, so we're going to use OAuth to # authenticate the user # Ask flask to generate the url corresponding to the login_callback # route. This is similar to using reverse() in django. redirect_uri = url_for('.login_callback', _external=True) client = APIClient(APP_ID, APP_SECRET) return redirect(client.authentication_url(redirect_uri))
def index(): # We don't have an access token, so we're going to use OAuth to # authenticate the user # Ask flask to generate the url corresponding to the login_callback # route. This is similar to using reverse() in django. redirect_uri = url_for('.login_callback', _external=True) client = APIClient(APP_ID, APP_SECRET) return redirect(client.authentication_url(redirect_uri))
def login_imap_callback(request): res = {'website': WEBSITE} # logger.info(request) code = request.GET['code'] APP_ID = "e2qdjgra07ea3p3idcv1bea1z" APP_SECRET = "dprso40e0tjqk989fab76hqq" # Exchange the authorization code for an access token client = APIClient(APP_ID, APP_SECRET) logger.info(code) access_token = client.token_for_code(code) logger.info(access_token) return HttpResponseRedirect('/editor')
def index(): # If the user has already connected to Google via OAuth, # `google.authorized` will be True. We also need to be sure that # we have a refresh token from Google. If we don't have both of those, # that indicates that we haven't correctly connected with Google. if not (google.authorized and "refresh_token" in google.token): # Google requires HTTPS. The template will display a handy warning, # unless we've overridden the check. return render_template( "before_google.html", insecure_override=os.environ.get("OAUTHLIB_INSECURE_TRANSPORT"), ) if "nylas_access_token" not in session: # The user has already connected to Google via OAuth, # but hasn't yet passed those credentials to Nylas. # We'll redirect the user to the right place to make that happen. return redirect(url_for("after_google")) # If we've gotten to this point, then the user has already connected # to both Google and Nylas. # Let's set up the SDK client with the OAuth token: client = APIClient( app_id=app.config["NYLAS_OAUTH_CLIENT_ID"], app_secret=app.config["NYLAS_OAUTH_CLIENT_SECRET"], access_token=session["nylas_access_token"], ) # We'll use the Nylas client to fetch information from Nylas # about the current user, and pass that to the template. account = client.account return render_template("after_connected.html", account=account, client=client)
def email_fetch(): client = APIClient(login["nylas_app_id"], login["nylas_app_secret"], login["nylas_token"]) for message in client.messages.where(unread=True): soup = BeautifulSoup(message.body, 'html.parser') message.mark_as_read( ) # Immediately mark as read to prevent email from being caught up to in the future print(str(message)) print(str(message["from"])) print(str(message["cc"])) print(soup.get_text()) if (message["from"][0]["email"] ).lower().find("@backtotheroots.com") > 0: # Get plaintext, feed to body_get which trims 'Thanks,' forward, find if there are any valid commands if not find_command(body_get(soup.get_text())): print(body_get(soup.get_text())) print("pre-sending-mail") mail_sending.send_mail_noattach( message_templates["invalid_command"], message["from"][0]["email"], "") return
def api_client_with_app_id(access_token, api_url, app_id, app_secret): return APIClient( app_id=app_id, app_secret=app_secret, access_token=access_token, api_server=api_url, )
def verify_auth_status(): """ This is an API that verifies the authorization status. Called when user loads up the page. """ from cloud_sql import sql_handler uid = flask.session['uid'] logging.info(f'verifying auth sync status for uid {uid}') access_token, email = sql_handler.get_nylas_authorize_info(uid) if not access_token: logging.info(f'The account {uid} has not authorized yet') response = flask.jsonify({'status': 'no auth'}) response.status_code = 402 return response try: nylas_client = APIClient( app_id=app.config["NYLAS_OAUTH_CLIENT_ID"], app_secret=app.config["NYLAS_OAUTH_CLIENT_SECRET"], access_token=access_token, ) sync_state = nylas_client.account.sync_state logging.info(f'Current syncing status is {sync_state}') logging.info(f'The account {uid} is in sync') response = flask.jsonify({'email': email or flask.session['email']}) response.status_code = 200 return response except Exception as e: # Here we simplify the status into binary cases. # for more statuses, check https://docs.nylas.com/reference#account-sync-status logging.warning(f'The account {uid} need resync') response = flask.jsonify({'status': 'Need resync'}) response.status_code = 200 return response
def files(): """ POST: upload attachment GET: get attachment status. """ from cloud_sql import sql_handler uid = flask.session.get('uid') data = flask.request.files logging.info(f'Receiving request {data} for session uid {uid}') access_token = sql_handler.get_nylas_access_token(uid) if not access_token: response = flask.jsonify({'status': 'no auth'}) response.status_code = 402 return response logging.info(f'Retrieved Nylas access token {access_token}') nylas = APIClient( app_id=app.config["NYLAS_OAUTH_CLIENT_ID"], app_secret=app.config["NYLAS_OAUTH_CLIENT_SECRET"], access_token=access_token ) if flask.request.method == 'POST': try: # check if the post request has the file part logging.info(f'{[key for key in flask.request.files.keys()]}') if 'file' not in flask.request.files and 'UploadFiles' not in flask.request.files: logging.info('No file part') return flask.redirect(flask.request.url) file = flask.request.files['UploadFiles'] or flask.request.files['file'] # if user does not select file, browser also # submit an empty part without filename if file.filename == '': logging.info('No selected file') return flask.redirect(flask.request.url) if file: filename = secure_filename(file.filename) logging.info(f'receiving file name {filename}') # file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename)) nylas_file = nylas.files.create() nylas_file.filename = file.filename nylas_file.stream = file # .save() saves the file to Nylas, file.id can then be used to attach the file to an email nylas_file.save() response = flask.jsonify({'file_id': nylas_file.id}) response.status_code = 200 return response except Exception as e: logging.error(f'Uploading attachment failed! Error message is {str(e)}') response = flask.jsonify({'error': f'Uploading attachment failed! Error message is {str(e)}'}) response.status_code = 400 return response elif flask.request.method == 'GET': file_id = flask.request.args.get('file_id') if not file_id: response = flask.jsonify({'error': 'need valid file_id query param'}) response.status_code = 412 nylas_file = nylas.files.get(file_id) response = flask.jsonify({'file': nylas_file}) response.status_code = 200 return response
def send_email(): from cloud_sql import sql_handler uid = flask.session.get('uid') data = flask.request.json logging.info(f'Receiving request {data} for session uid {uid}') access_token = sql_handler.get_nylas_access_token(uid) if not access_token: response = flask.jsonify({'status': 'no auth'}) response.status_code = 402 return response logging.info(f'Retrieved Nylas access token {access_token}') nylas = APIClient( app_id=app.config["NYLAS_OAUTH_CLIENT_ID"], app_secret=app.config["NYLAS_OAUTH_CLIENT_SECRET"], access_token=access_token ) try: draft = nylas.drafts.create() draft.subject = data.get('subject') draft.body = data.get('body') draft.to = data.get('to') draft.cc = data.get('cc') draft.send() logging.info('email sent successfully') response = flask.jsonify('email sent successfully') response.status_code = 200 return response except Exception as e: logging.error(f'Sending email failed! Error message is {str(e)}') response = flask.jsonify(str(e)) response.status_code = 400 return response
def emails(id): from nylas import APIClient nylas = APIClient(creds.CLIENT_ID, creds.CLIENT_SECRET, creds.ACCESS_TOKEN) data = nylas.messages.get(id) return render_template("emails.html", data=data)
def emailsearch(): from nylas import APIClient nylas = APIClient(creds.CLIENT_ID, creds.CLIENT_SECRET, creds.ACCESS_TOKEN) data = Search() return render_template("email-search.html", data=data)
def index(pagenr): session['contact_mails'] = [] session['contact_addresses'] = [] offset = pagenr # If we have an access_token, we may interact with the Nylas Server if 'access_token' in session: client = APIClient(APP_ID, APP_SECRET, session['access_token']) threads = None while not threads: try: # Get the latest message from namespace zero. threads = client.threads.where(**{'in': 'all', 'limit': 20, 'offset':0, 'view':'expanded' }) if not threads: # A new account takes a little time to sync print "No messages yet. Checking again in 2 seconds." time.sleep(2) except Exception as e: print(e.message) return Response("<html>An error occurred.</html>") # Format the output text = 'mit navn det står med prikker' for thread in threads: text += thread.snippet #text = "<html><h1>Here's a message from your inbox:</h1><b>From:</b> " #for sender in message["from"]: # text += "{} <{}>".format(sender['name'], sender['email']) #text += "<br /><b>Subject:</b> " + message.subject #text += "<br /><b>Body:</b> " + message.body #text += "</html>" # Return result to the client return Response(text) else: # We don't have an access token, so we're going to use OAuth to # authenticate the user # Ask flask to generate the url corresponding to the login_callback # route. This is similar to using reverse() in django. redirect_uri = url_for('.login_callback', _external=True) client = APIClient(APP_ID, APP_SECRET) return redirect(client.authentication_url(redirect_uri))
def callback(request): # Get the state saved in session expected_state = request.session.pop('auth_state', '') # Make the token request token = get_token_from_code(request.get_full_path(), expected_state) # Get the user's profile user = get_user(token) # #Get nylas code api_client = APIClient(app_id="57j65z6aezdxuocajwwegvkyx", app_secret="du2z08iomhm6remzvzyhk8bz9") response_body = { "client_id": api_client.app_id, "name": user['givenName'], "email_address": user['mail'], "provider": "office365", "settings": { "microsoft_client_id": settings['app_id'], "microsoft_client_secret": settings['app_secret'], "microsoft_refresh_token": token['refresh_token'], "redirect_uri": settings['redirect'], }, "scopes": "email.read_only,calendar" } nylas_authorize_resp = requests.post( "https://api.nylas.com/connect/authorize", json=response_body) nylas_code = nylas_authorize_resp.json()["code"] # Get nylas access_token nylas_token_data = { "client_id": api_client.app_id, "client_secret": api_client.app_secret, "code": nylas_code, } nylas_token_resp = requests.post("https://api.nylas.com/connect/token", json=nylas_token_data) if not nylas_token_resp.ok: message = nylas_token_resp.json()["message"] return requests.Response('Bad Request') nylas_access_token = nylas_token_resp.json()["access_token"] print(nylas_access_token) # Save token and user store_token(request, token) store_user(request, user) return HttpResponseRedirect(reverse('home'))
def revoke_auth(): """ This API essentially unauthorize and removes the customer from the Nylas authentication, along with auth for the Calendar and email accounts. """ from cloud_sql import sql_handler uid = flask.session['uid'] access_token = sql_handler.get_nylas_access_token(uid) if not access_token: logging.info(f'The account {uid} has not authorized yet') response = flask.jsonify({'status': 'no auth'}) response.status_code = 402 return response nylas_client = APIClient( app_id=app.config["NYLAS_OAUTH_CLIENT_ID"], app_secret=app.config["NYLAS_OAUTH_CLIENT_SECRET"], access_token=access_token, ) nylas_client.revoke_all_tokens() response = flask.jsonify('OK') response.status_code = 200 return response
def success(): if "nylas_access_token" not in session: return render_template("missing_token.html") client = APIClient( app_id=app.config["NYLAS_OAUTH_CLIENT_ID"], app_secret=app.config["NYLAS_OAUTH_CLIENT_SECRET"], access_token=session["nylas_access_token"], ) # We'll use the Nylas client to fetch information from Nylas # about the current user, and pass that to the template. account = client.account return render_template("success.html", account=account)
def events(event_id): from cloud_sql import sql_handler if not event_id: logging.error('Need a valid event id') response = flask.jsonify('Need a valid event id') response.status_code = 400 return response uid = flask.session.get('uid') access_token = sql_handler.get_nylas_access_token(uid) if not access_token: logging.info(f'The account {uid} has not authorized yet') response = flask.jsonify({'status': 'no auth'}) response.status_code = 402 return response nylas_client = APIClient( app_id=app.config["NYLAS_OAUTH_CLIENT_ID"], app_secret=app.config["NYLAS_OAUTH_CLIENT_SECRET"], access_token=access_token ) try: if flask.request.method == "GET": event = nylas_client.events.get(event_id) response = flask.jsonify(event_to_dict(event)) response.status_code = 200 return response elif flask.request.method == "DELETE": nylas_client.events.delete(event_id, notify_participants='true') response = flask.jsonify('{Status: OK}') response.status_code = 200 return response elif flask.request.method == "PUT": data = flask.request.json event = nylas_client.events.where(event_id=event_id).first() if not event: response = flask.jsonify('unable to modify event') response.status_code = 400 return response event = update_event_from_json(event, data, event.calendar_id) event.save(notify_participants='true') logging.info('Calendar event updated successfully') response = flask.jsonify('Calendar event updated successfully') response.status_code = 200 return response except Exception as e: response = flask.jsonify(str(e)) response.status_code = 400 return response
def get_email_thread(): from cloud_sql import sql_handler uid = flask.session.get('uid') data = flask.request.json logging.info(f'Receiving request {data} for session uid {uid}') search_email = flask.request.args.get('email') sender_email = flask.session.get('email') if not search_email: response = flask.jsonify({'error': 'need valid search_email query param'}) response.status_code = 412 return response access_token = sql_handler.get_nylas_access_token(uid) if not access_token: response = flask.jsonify({'status': 'no auth'}) response.status_code = 402 return response logging.info(f'Retrieved Nylas access token {access_token}') nylas = APIClient( app_id=app.config["NYLAS_OAUTH_CLIENT_ID"], app_secret=app.config["NYLAS_OAUTH_CLIENT_SECRET"], access_token=access_token ) try: # Return all messages found in the user's inbox full_message = [] messages_to = nylas.messages.where(to=search_email) for m in messages_to: message = message_to_dict(m) if len(message['from']) > 0 and message['from'][0]['email'] == sender_email: full_message.append(message) messages_from = nylas.messages.where(from_=search_email) for m in messages_from: message = message_to_dict(m) if len(message['to']) > 0 and message['to'][0]['email'] == sender_email: full_message.append(message) full_message.sort(key=lambda x: x['received_at'], reverse=True) response = flask.jsonify(full_message[0:50]) response.status_code = 200 return response except Exception as e: logging.error(f'Sending email failed! Error message is {str(e)}') response = flask.jsonify(str(e)) response.status_code = 400 return response
def create_calendar_event(): from cloud_sql import sql_handler uid = flask.session.get('uid') data = flask.request.json logging.info(f'Receiving request {data} for session uid {uid}') access_token = sql_handler.get_nylas_access_token(uid) if not access_token: response = flask.jsonify({'status': 'no auth'}) response.status_code = 402 return response nylas = APIClient( app_id=app.config["NYLAS_OAUTH_CLIENT_ID"], app_secret=app.config["NYLAS_OAUTH_CLIENT_SECRET"], access_token=access_token ) # Most user accounts have multiple calendars where events are stored calendars = nylas.calendars.all() calendar_id = '' for calendar in calendars: # Print the name and description of each calendar and whether or not the calendar is read only logging.info("Name: {} | Description: {} | Read Only: {} | ID: {}".format( calendar.name, calendar.description, calendar.read_only, calendar.id)) if calendar.read_only: continue calendar_id = calendar.id logging.info(f'Found a valid writable calendar {calendar.name}') if not calendar_id: response = flask.jsonify({'status': 'No writable calendar found!'}) response.status_code = 400 return response # Create a new event event = nylas.events.create() event = update_event_from_json(event, data, calendar_id) # .save()must be called to save the event to the third party provider # The event object must have values assigned to calendar_id and when before you can save it. event.save(notify_participants='true') # notify_participants='true' will send a notification email to # all email addresses specified in the participant subobject logging.info('calendar event created successfully') response = flask.jsonify('calendar event created successfully') response.status_code = 200 return response
def send_email_util(subject, body, to_email, to_name, bcc_email='*****@*****.**', bcc_name='lifo customer support', uid=None): """ This method is a generic email sending util without attachments. """ from cloud_sql import sql_handler if not uid: uid = flask.session.get('uid') access_token = sql_handler.get_nylas_access_token(uid) if not access_token: response = flask.jsonify({'status': 'no auth'}) response.status_code = 402 return response logging.info(f'Retrieved Nylas access token') nylas = APIClient( app_id=app.config["NYLAS_OAUTH_CLIENT_ID"], app_secret=app.config["NYLAS_OAUTH_CLIENT_SECRET"], access_token=access_token ) try: draft = nylas.drafts.create() draft.subject = subject draft.to = [{'email': to_email, 'name': to_name}] # bcc our Lifo's internal support account to allow better tracking. draft.bcc = [{'email': bcc_email, 'name': bcc_name}] draft.body = body draft.tracking = {'links': 'true', 'opens': 'true', 'thread_replies': 'true', } draft.send() logging.info('email sent successfully') response = flask.jsonify('email sent successfully') response.status_code = 200 return response except Exception as e: logging.error(f'Sending email failed! Error message is {str(e)}') response = flask.jsonify(str(e)) response.status_code = 400 return response
def authorize(request): api_client = APIClient(app_id="57j65z6aezdxuocajwwegvkyx", app_secret="du2z08iomhm6remzvzyhk8bz9") response_body = { "client_id": api_client.app_id, "name": "alexandra", "email_address": request.data.get('email'), "provider": "outlook", "settings": { "username": request.data.get('email'), "password": request.data.get('password'), } } nylas_authorize_resp = requests.post( "https://api.nylas.com/connect/authorize", json=response_body) print(nylas_authorize_resp.json()) # nylas_code = nylas_authorize_resp.json()["code"] nylas_code = 'd80cOfUCvwW-teOcAtvh' state = 'WM6D' nylas_token_data = { "client_id": api_client.app_id, "client_secret": api_client.app_secret, "code": nylas_code, "state": state } nylas_token_resp = requests.post("https://api.nylas.com/connect/token", json=nylas_token_data) if not nylas_token_resp.ok: message = nylas_token_resp.json()["message"] return Response('Bad Request') nylas_access_token = nylas_token_resp.json()["access_token"] data = {"code": nylas_code, "access_token": nylas_access_token} return Response(data)
def index(): if 'google_credentials' not in flask.session: return flask.render_template('index.html') # The user has authorized with google at this point but we will need to # connect the account to Nylas if 'nylas_access_token' not in flask.session: google_credentials = flask.session['google_credentials'] google_access_token = google_credentials['access_token'] email_address = get_email(google_access_token) google_refresh_token = google_credentials['refresh_token'] connect_to_nylas(google_refresh_token, email_address) return flask.redirect(flask.url_for('index')) # Google account has been setup, let's use Nylas' python SDK to retrieve an # email client = APIClient(NYLAS_CLIENT_ID, NYLAS_CLIENT_SECRET, flask.session['nylas_access_token']) # Display the latest email message! return client.threads.first().messages.first().body
def get_thread_by_id(): from cloud_sql import sql_handler uid = flask.session.get('uid') data = flask.request.json logging.info(f'Receiving request {data} for session uid {uid}') thread_id = flask.request.args.get('thread_id') if not thread_id: response = flask.jsonify({'error': 'need valid thread_id query param'}) response.status_code = 412 return response access_token = sql_handler.get_nylas_access_token(uid) if not access_token: response = flask.jsonify({'status': 'no auth'}) response.status_code = 402 return response logging.info(f'Retrieved Nylas access token {access_token}') nylas = APIClient( app_id=app.config["NYLAS_OAUTH_CLIENT_ID"], app_secret=app.config["NYLAS_OAUTH_CLIENT_SECRET"], access_token=access_token ) try: full_message = [] messages = nylas.messages.where(thread_id=thread_id) for m in messages: message = message_to_dict(m) full_message.append(message) full_message.sort(key=lambda x: x['received_at']) response = flask.jsonify(full_message) response.status_code = 200 return response except Exception as e: logging.error(f'Sending email failed! Error message is {str(e)}') response = flask.jsonify(str(e)) response.status_code = 400 return response
def index(): # If the user has already connected to Nylas via OAuth, # `nylas.authorized` will be True. Otherwise, it will be False. if not nylas.authorized: # OAuth requires HTTPS. The template will display a handy warning, # unless we've overridden the check. return render_template( "before_authorized.html", insecure_override=os.environ.get("OAUTHLIB_INSECURE_TRANSPORT"), ) # If we've gotten to this point, then the user has already connected # to Nylas via OAuth. Let's set up the SDK client with the OAuth token: nylas_client = APIClient( app_id=app.config["NYLAS_OAUTH_CLIENT_ID"], app_secret=app.config["NYLAS_OAUTH_CLIENT_SECRET"], access_token=nylas.access_token, ) # We'll use the Nylas client to fetch information from Nylas # about the current user, and pass that to the template. account = nylas_client.account return render_template("after_authorized.html", account=account)
def get_lifo_events(): """ Currently we rely on the hardcoded LIFO_CALENDAR_EVENT_SIGNATURE for events filtering. In future we may want to save all the events created by our product, and then get accordingly. But this will force us to fully manage the events life cycle. """ from cloud_sql import sql_handler uid = flask.session.get('uid') access_token = sql_handler.get_nylas_access_token(uid) if not access_token: logging.info(f'The account {uid} has not authorized yet') response = flask.jsonify({'status': 'no auth'}) response.status_code = 402 return response nylas_client = APIClient( app_id=app.config["NYLAS_OAUTH_CLIENT_ID"], app_secret=app.config["NYLAS_OAUTH_CLIENT_SECRET"], access_token=access_token ) events = nylas_client.events.where(description=LIFO_CALENDAR_EVENT_SIGNATURE) logging.info(f'Found events {str(events)}') response = flask.jsonify([event_to_dict(event) for event in events]) response.status_code = 200 return response
def threads_contacts(offset): # If we have an access_token, we may interact with the Nylas Server #session['access_token'] = 'aC8stzQsDBR0ywlOmhCuyIBdu5uJYc' if 'access_token' in session: client = APIClient(APP_ID, APP_SECRET, session['access_token']) print session['access_token'] if 'threads_contacts' not in session: session['threads_contacts'] = [] if 'threads_contacts_addresses' not in session: session['threads_contacts_addresses'] = [] if 'threads_contacts_offset' not in session: session['threads_contacts_offset'] = 0 if 'threads_contacts_ids' not in session: session['threads_contacts_ids'] = [] last_thread = False #session['threads_contacts'] = [] #session['threads_contacts_addresses'] = [] #session['threads_contacts_offset'] = 0 #session['threads_contacts_ids'] = [] while (len(session['threads_contacts']) + 1 < (offset + 1) * 10): threadcounter = 0 for thread in client.threads.where(offset=session['threads_contacts_offset'], limit=99, in_='inbox'): #**{'in':'all', 'limit':40, 'offset':2}: threadcounter = threadcounter + 1 if len(thread.participants) <= 2: if len(thread.participants) == 1: name = thread.participants[0]['name'] email = thread.participants[0]['email'] if len(thread.participants) == 2: for participant in thread.participants: if participant['email'] != '*****@*****.**': name = participant['name'] email = participant['email'] if email not in session['threads_contacts_addresses'] and thread['id'] not in session['threads_contacts_ids']: contact_thread = { 'id': thread['id'], 'date': thread['last_message_timestamp'], 'name': name, #thread.participants[0]['name'], 'email': email, #thread.participants[0]['email'], 'snippet': thread['snippet'], 'unread': thread['unread'], 'type': 'email' } session['threads_contacts'].append(contact_thread) session['threads_contacts_addresses'].append(email) session['threads_contacts_ids'].append(thread['id']) if (len(thread.participants) > 2) and (thread['id'] not in session['threads_contacts_ids']): name = '' emails = '' for participant in thread.participants: if participant['name']: name += participant['name'] + ', ' emails += participant['email'] + ', ' else: name += participant['email'] + ', ' emails += participant['email'] + ', ' contact_thread = { 'id': thread['id'], 'date': thread['last_message_timestamp'], 'name': name, 'email': emails, 'snippet': thread['snippet'], 'unread': thread['unread'], 'type': 'thread' } session['threads_contacts'].append(contact_thread) session['threads_contacts_ids'].append(thread['id']) session['threads_contacts_offset'] = session['threads_contacts_offset'] + 1 if threadcounter < 99: last_thread = True break # Return result to the client if offset == 0: start = 0 end = 10 else: start = offset * 10 end = (offset + 1) * 10 response = {'contacts': session['threads_contacts'][start:end], 'lastThread': last_thread} js = json.dumps(response) resp = Response(js, status=200, mimetype='application/json') return resp else: # We don't have an access token, so we're going to use OAuth to # authenticate the user # Ask flask to generate the url corresponding to the login_callback # route. This is similar to using reverse() in django. redirect_uri = url_for('.login_callback', _external=True) client = APIClient(APP_ID, APP_SECRET) return redirect(client.authentication_url(redirect_uri))
def api_client(api_url): return APIClient(app_id=None, app_secret=None, access_token=None, api_server=api_url)
""" This example will only work if you replace the fake configuration values in `config.json` with real configuration values. The following config values need to be replaced: {keys} Consult the README.md file in this directory for more information. """ ).format(keys=", ".join(cfg_needs_replacing)) print(message, file=sys.stderr) sys.exit(1) # Teach Flask how to find out that it's behind an ngrok proxy app.wsgi_app = ProxyFix(app.wsgi_app) redirect_url = "https://nylas-customer-example.herokuapp.com/login_callback" client = APIClient(app.config["NYLAS_OAUTH_CLIENT_ID"], app.config["NYLAS_OAUTH_CLIENT_SECRET"]) # Define what Flask should do when someone visits the root URL of this website. @app.route("/", methods=['GET']) def index(): # If the user has already connected to Nylas via OAuth, # `nylas.authorized` will be True. Otherwise, it will be False. if session.get('access_token') is not None: # If we've gotten to this point, then the user has already connected # to Nylas via OAuth. Let's set up the SDK client with the OAuth token: client.access_token = session['access_token'] # We'll use the Nylas client to fetch information from Nylas # about the current user, and pass that to the template. try:
#!/usr/bin/python import time from nylas import APIClient from nylas.util import generate_id APP_ID = '[YOUR_APP_ID]' APP_SECRET = '[YOUR_APP_SECRET]' ACCESS_TOKEN = '[YOUR_ACCESS_TOKEN]' client = APIClient(APP_ID, APP_SECRET, ACCESS_TOKEN) subject = generate_id() f = open('test.py', 'r') data = f.read() f.close() myfile = client.files.create() myfile.filename = 'test.py' myfile.data = data # Create a new draft draft = client.drafts.create() draft.to = [{'name': 'Charles Gruenwald', 'email': '*****@*****.**'}] draft.subject = subject draft.body = "" draft.attach(myfile) draft.send() x = 0 th = client.threads.where({'in': 'Sent', 'subject': subject}).first()
def authorize(): """ This API authenticate for a chosen scope, and saves the nylas access code to cloud sql. Note: this API is the single entry point for authorization flow, and it will deactivate all previous access tokens for the given Nylas id. :return: flask response, 200 if success, 400 if failed. """ from cloud_sql import sql_handler nylas_code = flask.request.args.get('code') error = flask.request.args.get('error') uid = flask.session['uid'] logging.info(f'verifying auth sync status for uid {uid}') access_token = sql_handler.get_nylas_access_token(uid) # this is to handle potential authorization errors including access denied by customers. if error: logging.error(f'Authorization failed due to error: {error}') response = flask.jsonify(error) response.status_code = 400 return response nylas_client = APIClient(app_id=app.config["NYLAS_OAUTH_CLIENT_ID"], app_secret=app.config["NYLAS_OAUTH_CLIENT_SECRET"]) if not nylas_code: scope = flask.request.args.get('scope') if not scope: logging.error('Need a valid scope string, currently supporting: calendar,email.send,email.modify') scope = 'calendar,email.send,email.modify' redirect_url = 'http://auth.lifo.ai/authorize' logging.info(f'receiving request for scope {scope}, and redirect to {redirect_url}') flask.session['scope'] = scope # Redirect your user to the auth_url auth_url = nylas_client.authentication_url( redirect_url, scopes=scope ) return flask.redirect(auth_url) else: # note, here we have not handled the declined auth case logging.info(f'authentication success with code: {nylas_code}') access_token = nylas_client.token_for_code(nylas_code) nylas_client = APIClient( app_id=app.config["NYLAS_OAUTH_CLIENT_ID"], app_secret=app.config["NYLAS_OAUTH_CLIENT_SECRET"], access_token=access_token, ) # Revoke all tokens except for the new one nylas_client.revoke_all_tokens(keep_access_token=access_token) account = nylas_client.account nylas_account_id = account.id nylas_email = account.email_address uid = flask.session['uid'] scope = flask.session['scope'] logging.info(f'handling auth for firebase uid: {uid} for scope {scope} and nylas id {nylas_account_id}') # Note: here we automatically handle the Nylas id changing case, as each user is recognized by their firebase # uid, and any new Nylas ids will be overwritten. This does bring in limitations: a user can only authorize one # Calendar account, which is not an issue for foreseeable future. sql_handler.save_nylas_token(uid, nylas_access_token=access_token, nylas_account_id=nylas_account_id, email=nylas_email) return render_template("authorize_succeed.html")
def send_single_email_with_template(): """ This method sends email with template, and replace: ${receiver_name} with to_name ${file_id} (if any) with file_id """ from cloud_sql import sql_handler uid = flask.session.get('uid') data = flask.request.json logging.info(f'Receiving request {data} for session uid {uid}') access_token = sql_handler.get_nylas_access_token(uid) if not access_token: response = flask.jsonify({'status': 'no auth'}) response.status_code = 402 return response logging.info(f'Retrieved nylas access token') nylas = APIClient( app_id=app.config["NYLAS_OAUTH_CLIENT_ID"], app_secret=app.config["NYLAS_OAUTH_CLIENT_SECRET"], access_token=access_token ) try: draft = nylas.drafts.create() if not data.get('subject') or not data.get('body') or not data.get('to_email') or not data.get('to_name'): response = flask.jsonify({'error': 'need valid file_id query param'}) response.status_code = 412 draft.subject = data.get('subject') body = data.get('body') #Note: should to_name be account_id instead? body = body.replace("$(receiver_name)", data.get('to_name')) # note: need to anonymize the email for external url usage. body = body.replace("$(inf_email)", data.get('to_email')) brand_campaign_id = data.get('brand_campaign_id') body = body.replace("$(brand_campaign_id)", brand_campaign_id) draft.to = [{'email': data.get('to_email'), 'name': data.get('to_name')}] # bcc our Lifo's internal support account to allow better tracking. draft.bcc = [{'email': '*****@*****.**', 'name': 'lifo customer support'}] if data.get('file_id'): file = nylas.files.get(data.get('file_id')) draft.attach(file) body = body.replace("$(file_id)", file.id) # when reply a thread if data.get('reply_to_message_id'): draft.reply_to_message_id = data.get('reply_to_message_id') draft.body = body draft.tracking = {'links': 'true', 'opens': 'true', 'thread_replies': 'true', 'payload': data.get('campaign_name') } """ Here we access influencer sub_collection under each brand campaign. This is to replicate the following function from Nodejs side under api_nodejs service. function access_influencer_subcollection(brand_campaign_id) { return db.collection(BRAND_CAMPAIGN_COLLECTIONS).doc(brand_campaign_id) .collection(INFLUENCER_COLLECTIONS); } """ inf_account_id = data.get('account_id') if inf_account_id != 'lifo' and data.get('to_name') != 'lifo' and 'lifo.ai' not in data.get('to_email'): emails_ref = db.collection(BRAND_CAMPAIGN_COLLECTIONS, brand_campaign_id, INFLUENCER_COLLECTIONS, inf_account_id, EMAILS_COLLECTIONS) hash_value = hashlib.sha256(body.encode('utf-8')).hexdigest() same_email_list = emails_ref.where('subject', u'==', draft.subject).where('body_hash', u'==', hash_value).get() logging.info(f'Found repeated email list {same_email_list}') if len(same_email_list) > 0: logging.info('Repeatedly sending the same emails!') response = flask.jsonify({'status': 'Repeated emails'}) response.status_code = 429 return response email_history = { 'ts': firestore.SERVER_TIMESTAMP, 'body': draft.body, 'body_hash': hash_value, 'subject': draft.subject, 'to': draft.to, 'file_id': data.get('file_id') } emails_ref.document().set(email_history) send_result = draft.send() logging.info(send_result) # Update influencer status influencer_ref = db.document(BRAND_CAMPAIGN_COLLECTIONS, brand_campaign_id, INFLUENCER_COLLECTIONS, inf_account_id) influencer_update_body = {} if data.get('for_contract'): influencer_update_body['inf_contract_status'] = 'Email sent' if not data.get('reply_to_message_id'): influencer_update_body['inf_contract_thread'] = send_result['thread_id'] influencer_update_body['contract_received_time'] = time.time() else: influencer_update_body['inf_contacting_status'] = 'Email sent' if not data.get('reply_to_message_id'): influencer_update_body['inf_offer_thread'] = send_result['thread_id'] influencer_update_body['offer_received_time'] = time.time() influencer_ref.set( influencer_update_body, merge=True ) logging.info('email sent successfully') response = flask.jsonify(send_result) response.status_code = 200 return response except Exception as e: logging.error(f'Sending email failed! Error message is {str(e)}') response = flask.jsonify(str(e)) response.status_code = 400 return response
def send_email_to_brand(): """ This method sends email with template, and replace: ${receiver_name} with to_name ${file_id} (if any) with file_id """ from cloud_sql import sql_handler uid = flask.session.get('uid') sender_name = flask.session.get('name') sender_email = flask.session.get('email') # Some user does not have 'name' field, add a temp hack here if not sender_name: sender_name = sender_email data = flask.request.json logging.info(f'Receiving request {data} for session uid {uid}') access_token = sql_handler.get_nylas_access_token(uid) if not access_token: response = flask.jsonify({'status': 'no auth'}) response.status_code = 402 return response logging.info(f'Retrieved nylas access token {access_token}') nylas = APIClient( app_id=app.config["NYLAS_OAUTH_CLIENT_ID"], app_secret=app.config["NYLAS_OAUTH_CLIENT_SECRET"], access_token=access_token ) try: draft = nylas.drafts.create() if not data.get('subject') or not data.get('body') or not data.get('to_email') or not data.get('to_name'): response = flask.jsonify({'error': 'need valid file_id query param'}) response.status_code = 412 draft.subject = data.get('subject') body = data.get('body') body = body.replace("$(receiver_name)", data.get('to_name')) draft.to = [{'email': data.get('to_email'), 'name': data.get('to_name')}] # bcc our Lifo's internal support account to allow better tracking. draft.bcc = [{'email': '*****@*****.**', 'name': 'lifo customer support'}] if data.get('file_id'): file = nylas.files.get(data.get('file_id')) draft.attach(file) body = body.replace("$(file_id)", file.id) draft.body = body draft.tracking = {'links': 'true', 'opens': 'true', 'thread_replies': 'true', 'payload': data.get('campaign_name') or f'{sender_name} <{sender_email}>' } brand_campaign_id = data.get('brand_campaign_id') emails_ref = db.collection(BRAND_CAMPAIGN_COLLECTIONS, brand_campaign_id, EMAILS_COLLECTIONS) email_history = { 'ts': firestore.SERVER_TIMESTAMP, 'body': draft.body, 'subject': draft.subject, 'to': draft.to, 'file_id': data.get('file_id') } emails_ref.document().set(email_history) draft.send() logging.info('email sent successfully') response = flask.jsonify('email sent successfully') response.status_code = 200 return response except Exception as e: logging.error(f'Sending email failed! Error message is {str(e)}') response = flask.jsonify(str(e)) response.status_code = 400 return response