Samfredoly commited on
Commit
44b039f
·
verified ·
1 Parent(s): 57a18ee

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +97 -25
app.py CHANGED
@@ -1,27 +1,39 @@
1
  import logging
2
  import ssl
 
 
 
3
  from aiosmtpd.controller import Controller
4
  from aiosmtpd.handlers import Sink
5
  from aiosmtpd.smtp import SMTP, AuthResult, LoginPassword
6
- from email.policy import default
7
- from typing import Optional
 
 
 
8
 
9
  # Configure logging
10
  logging.basicConfig(level=logging.INFO)
11
- logger = logging.getLogger("smtp_server")
12
 
13
  # SMTP Server Configuration
14
- SMTP_HOST = "0.0.0.0" # Bind to all interfaces
15
- SMTP_PORT = 587 # Standard SMTP submission port
16
- TLS_CERTFILE = "cert.pem" # Path to your SSL certificate
17
- TLS_KEYFILE = "key.pem" # Path to your SSL private key
 
 
 
18
 
19
- # Authentication Credentials (for demo purposes; use a secure vault in production)
20
  VALID_USERS = {
21
- "user1": "password1",
22
- "user2": "password2",
23
  }
24
 
 
 
 
 
25
  class AuthenticatedSMTPHandler(Sink):
26
  async def handle_AUTH(self, server: SMTP, args: str, mechanism: str) -> Optional[AuthResult]:
27
  if mechanism.upper() != "LOGIN":
@@ -40,39 +52,99 @@ class AuthenticatedSMTPHandler(Sink):
40
  return AuthResult(success=False, message="Authentication failed")
41
 
42
  async def handle_DATA(self, server: SMTP, session, envelope):
43
- # Log the received email
44
  logger.info(f"Received email from: {envelope.mail_from}")
45
  logger.info(f"Recipients: {envelope.rcpt_tos}")
46
  logger.info(f"Message data:\n{envelope.content.decode('utf-8')}")
47
  return "250 Message accepted for delivery"
48
 
 
49
  def start_smtp_server():
50
- # Create SSL context for TLS
51
  ssl_context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
52
- ssl_context.load_cert_chain(TLS_CERTFILE, TLS_KEYFILE)
53
 
54
- # Create the SMTP handler
55
  handler = AuthenticatedSMTPHandler()
56
-
57
- # Start the SMTP server with TLS and authentication
58
  controller = Controller(
59
  handler,
60
  hostname=SMTP_HOST,
61
  port=SMTP_PORT,
62
  enable_SMTPUTF8=True,
63
- ssl_context=ssl_context,
64
  auth_required=True,
65
  )
66
 
67
- logger.info(f"Starting SMTP server on {SMTP_HOST}:{SMTP_PORT} with TLS and authentication...")
68
  controller.start()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
69
  try:
70
- # Keep the server running
71
- while True:
72
- pass
73
  except KeyboardInterrupt:
74
  logger.info("Shutting down SMTP server...")
75
- controller.stop()
76
-
77
- if __name__ == "__main__":
78
- start_smtp_server()
 
1
  import logging
2
  import ssl
3
+ import smtplib
4
+ from email.mime.text import MIMEText
5
+ from flask import Flask, request, jsonify
6
  from aiosmtpd.controller import Controller
7
  from aiosmtpd.handlers import Sink
8
  from aiosmtpd.smtp import SMTP, AuthResult, LoginPassword
9
+ from dotenv import load_dotenv
10
+ import os
11
+
12
+ # Load environment variables
13
+ load_dotenv()
14
 
15
  # Configure logging
16
  logging.basicConfig(level=logging.INFO)
17
+ logger = logging.getLogger("app")
18
 
19
  # SMTP Server Configuration
20
+ SMTP_HOST = "0.0.0.0"
21
+ SMTP_PORT = 587
22
+ SMTP_USER = os.getenv("SMTP_USER", "noreply@yourdomain.com") # Use a valid domain
23
+ SMTP_PASSWORD = os.getenv("SMTP_PASSWORD", "password")
24
+
25
+ # WhatsApp webhook verification token
26
+ WHATSAPP_WEBHOOK_TOKEN = os.getenv("WHATSAPP_WEBHOOK_TOKEN", "your_webhook_token")
27
 
28
+ # Authentication Credentials
29
  VALID_USERS = {
30
+ SMTP_USER: SMTP_PASSWORD,
 
31
  }
32
 
33
+ # Flask app for WhatsApp bot
34
+ app = Flask(__name__)
35
+
36
+ # SMTP Server Handler
37
  class AuthenticatedSMTPHandler(Sink):
38
  async def handle_AUTH(self, server: SMTP, args: str, mechanism: str) -> Optional[AuthResult]:
39
  if mechanism.upper() != "LOGIN":
 
52
  return AuthResult(success=False, message="Authentication failed")
53
 
54
  async def handle_DATA(self, server: SMTP, session, envelope):
 
55
  logger.info(f"Received email from: {envelope.mail_from}")
56
  logger.info(f"Recipients: {envelope.rcpt_tos}")
57
  logger.info(f"Message data:\n{envelope.content.decode('utf-8')}")
58
  return "250 Message accepted for delivery"
59
 
60
+ # Start SMTP Server
61
  def start_smtp_server():
62
+ # Enable SSL/TLS
63
  ssl_context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
64
+ ssl_context.load_cert_chain("cert.pem", "key.pem") # Load your certificate and key
65
 
 
66
  handler = AuthenticatedSMTPHandler()
 
 
67
  controller = Controller(
68
  handler,
69
  hostname=SMTP_HOST,
70
  port=SMTP_PORT,
71
  enable_SMTPUTF8=True,
72
+ ssl_context=ssl_context, # Enable SSL/TLS
73
  auth_required=True,
74
  )
75
 
76
+ logger.info(f"Starting SMTP server on {SMTP_HOST}:{SMTP_PORT} with SSL/TLS...")
77
  controller.start()
78
+ return controller
79
+
80
+ # WhatsApp Webhook
81
+ @app.route("/webhook", methods=["GET", "POST"])
82
+ def webhook():
83
+ if request.method == "GET":
84
+ # Verify webhook
85
+ mode = request.args.get("hub.mode")
86
+ token = request.args.get("hub.verify_token")
87
+ challenge = request.args.get("hub.challenge")
88
+
89
+ if mode == "subscribe" and token == WHATSAPP_WEBHOOK_TOKEN:
90
+ logger.info("Webhook verified successfully")
91
+ return challenge, 200
92
+ else:
93
+ logger.error("Webhook verification failed")
94
+ return "Verification failed", 403
95
+
96
+ elif request.method == "POST":
97
+ # Handle incoming messages
98
+ data = request.json
99
+ logger.info(f"Incoming webhook data: {data}")
100
+
101
+ try:
102
+ # Extract message details
103
+ message = data["entry"][0]["changes"][0]["value"]["messages"][0]
104
+ sender_number = message["from"]
105
+ message_body = message["text"]["body"]
106
+
107
+ # Parse the message (format: "send email to <recipient> subject <subject> body <body>")
108
+ parts = message_body.split("subject")
109
+ recipient_part = parts[0].replace("send email to", "").strip()
110
+ subject_part = parts[1].split("body")[0].strip()
111
+ body_part = parts[1].split("body")[1].strip()
112
+
113
+ recipient = recipient_part
114
+ subject = subject_part
115
+ body = body_part
116
+
117
+ # Send email
118
+ send_email(recipient, subject, body)
119
+ response_msg = f"Email sent to {recipient} with subject '{subject}'."
120
+ except Exception as e:
121
+ logger.error(f"Error processing message: {e}")
122
+ response_msg = "Invalid format. Use: 'send email to <recipient> subject <subject> body <body>'."
123
+
124
+ # Send response back to WhatsApp
125
+ return jsonify({"status": "success", "message": response_msg}), 200
126
+
127
+ # Send Email Function
128
+ def send_email(recipient, subject, body):
129
+ msg = MIMEText(body)
130
+ msg['Subject'] = subject
131
+ msg['From'] = SMTP_USER # Use a valid "From" address
132
+ msg['To'] = recipient
133
+
134
+ with smtplib.SMTP(SMTP_HOST, SMTP_PORT) as server:
135
+ server.starttls() # Enable TLS
136
+ server.login(SMTP_USER, SMTP_PASSWORD)
137
+ server.sendmail(SMTP_USER, [recipient], msg.as_string())
138
+ logger.info(f"Email sent to {recipient}")
139
+
140
+ # Main Function
141
+ if __name__ == "__main__":
142
+ # Start SMTP server
143
+ smtp_controller = start_smtp_server()
144
+
145
+ # Start Flask app for WhatsApp bot
146
  try:
147
+ app.run(host="0.0.0.0", port=5000)
 
 
148
  except KeyboardInterrupt:
149
  logger.info("Shutting down SMTP server...")
150
+ smtp_controller.stop()