-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathapp.py
More file actions
155 lines (122 loc) · 4.76 KB
/
app.py
File metadata and controls
155 lines (122 loc) · 4.76 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
"""Flask Application."""
from concurrent.futures import ThreadPoolExecutor
from datetime import datetime
import json
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from flask import Flask, request, Blueprint, jsonify
import requests
from twilio.twiml.messaging_response import MessagingResponse
from utils import get_configs
app = Flask(__name__)
GATEWAY_SERVER_HOST = get_configs("GATEWAY_SERVER_HOST", strict=True)
GATEWAY_SERVER_PORT = get_configs("GATEWAY_SERVER_PORT", strict=True)
SMTP_HOST = get_configs("SMTP_HOST", default_value="smtp.gmail.com")
SMTP_PORT = int(get_configs("SMTP_PORT", default_value="587"))
SMTP_USERNAME = get_configs("SMTP_USERNAME")
SMTP_PASSWORD = get_configs("SMTP_PASSWORD")
SMTP_FROM_ADDRESS = get_configs("SMTP_FROM_ADDRESS")
SMTP_TO_ADDRESS = get_configs("SMTP_TO_ADDRESS")
PORT = get_configs("PORT", default_value=7000)
api_bp_v1 = Blueprint("api", __name__, url_prefix="/v1")
gateway_server_urls = (f"{GATEWAY_SERVER_HOST}:{GATEWAY_SERVER_PORT}/v3/publish",)
def gateway_server_request(url, payload):
"""
Send a POST request to the specified gateway server URL.
Args:
url (str): The URL to send the request to.
payload (dict): The payload to send in the request.
Returns:
requests.Response: The response from the server.
"""
try:
response = requests.post(url, json=payload, timeout=10)
app.logger.info(
"Response from Gateway Server (%s): %s -- %s",
url,
response.status_code,
response.text,
)
return response
except requests.RequestException as e:
app.logger.error("Failed to send request to %s: %s", url, e)
return None
def send_smtp_email(payload):
"""
Send an email via SMTP containing SMS details.
Args:
payload (dict): The payload containing SMS details.
Returns:
bool: True if email was sent successfully, False otherwise.
"""
if not all(
[SMTP_HOST, SMTP_USERNAME, SMTP_PASSWORD, SMTP_FROM_ADDRESS, SMTP_TO_ADDRESS]
):
app.logger.warning(
"SMTP configuration incomplete. Skipping email notification."
)
return False
try:
msg = MIMEMultipart()
msg["From"] = SMTP_FROM_ADDRESS
msg["To"] = SMTP_TO_ADDRESS
msg["Subject"] = "RelaySMS-Twilio Incoming SMS"
email_body = json.dumps(payload, indent=4)
msg.attach(MIMEText(email_body, "plain"))
with smtplib.SMTP(SMTP_HOST, SMTP_PORT) as server:
server.starttls()
server.login(SMTP_USERNAME, SMTP_PASSWORD)
server.send_message(msg)
app.logger.info("Email sent successfully.")
return True
except Exception as e:
app.logger.error("Failed to send email: %s", e)
return False
@api_bp_v1.route("/twilio-sms", methods=["GET", "POST"])
def twilio_incoming_sms():
"""
Endpoint to handle incoming messages from Twilio.
"""
resp = MessagingResponse()
try:
data = request.form.to_dict()
app.logger.debug("Received data from Twilio: %s", data)
if not data.get("From"):
app.logger.error("Missing required field: 'From'")
return jsonify({"error": "Missing required field: 'From'"}), 400
if not data.get("Body"):
app.logger.error("Missing required field: 'Body'")
return jsonify({"error": "Missing required field: 'Body'"}), 400
now_ms = int(datetime.now().timestamp() * 1000)
publish_payload = {
"address": data["From"],
"text": data["Body"],
"date": str(now_ms),
"date_sent": str(now_ms),
}
with ThreadPoolExecutor(max_workers=len(gateway_server_urls) + 1) as executor:
gateway_futures = [
executor.submit(gateway_server_request, url, publish_payload)
for url in gateway_server_urls
]
smtp_future = executor.submit(send_smtp_email, publish_payload)
for future in gateway_futures:
try:
future.result(timeout=15)
except Exception as e:
app.logger.error("Gateway server request failed: %s", e)
try:
smtp_future.result(timeout=15)
except Exception as e:
app.logger.error("SMTP email sending failed: %s", e)
return str(resp)
except Exception as e:
app.logger.exception("Error processing incoming Twilio SMS: %s", e)
return (
jsonify({"error": "Oops! Something went wrong. Please try again later."}),
500,
)
app.register_blueprint(api_bp_v1)
if __name__ == "__main__":
app.run(debug=True, port=PORT)