-
Notifications
You must be signed in to change notification settings - Fork 0
/
sendemail.py
166 lines (140 loc) · 5.29 KB
/
sendemail.py
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
156
157
158
159
160
161
162
163
164
165
166
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from typing import Protocol
# Constants
DEFAULT_EMAIL = "[email protected]"
LOGIN = "admin"
PASSWORD = "admin"
# Protocol Definition for SMTP Server
class EmailServer(Protocol):
@property
def _host(self) -> str:
...
def connect(self, host: str, port: int) -> None:
...
def starttls(self) -> None:
...
def login(self, login: str, password: str) -> None:
...
def quit(self) -> None:
...
def sendmail(self, from_address: str, to_address: str, message: str) -> None:
...
# Concrete SMTP Server Class
class SmtpLibEmailServer:
def __init__(self, host: str, port: int):
self._host = f"{host}:{port}"
self._connection = None
def connect(self, host: str, port: int) -> None:
print(f"Connecting to SMTP server {host}:{port}...")
self._connection = smtplib.SMTP(host, port)
self._connection.set_debuglevel(1) # Enable detailed debug output for the SMTP session
self._connection.ehlo() # Extended SMTP greeting
print("Connected to SMTP server.")
def starttls(self) -> None:
if self._connection:
print("Starting TLS encryption...")
self._connection.starttls()
self._connection.ehlo()
print("TLS encryption started.")
def login(self, login: str, password: str) -> None:
if self._connection:
print(f"Logging in as {login}...")
self._connection.login(login, password)
print("Logged in successfully.")
def quit(self) -> None:
if self._connection:
print("Quitting SMTP server...")
self._connection.quit()
self._connection = None
print("Disconnected from SMTP server.")
def sendmail(self, from_address: str, to_address: str, message: str) -> None:
if self._connection:
print(f"Sending email from {from_address} to {to_address}...")
self._connection.sendmail(from_address, to_address, message)
print("Email sent successfully.")
# Email Client Class
class EmailClient:
def __init__(
self,
smtp_server: EmailServer,
login: str | None = None,
password: str | None = None,
name: str | None = None,
to_address: str = DEFAULT_EMAIL,
):
self._server = smtp_server
host, port = str(smtp_server._host).split(":") # type: ignore
self._host: str = host
self._port = int(port)
if not login or not password:
self._login, self._password = LOGIN, PASSWORD
else:
self._login, self._password = login, password
self.name = name
self.to_address = to_address
def _connect(self) -> None:
try:
self._server.connect(self._host, self._port)
self._server.starttls()
self._server.login(self._login, self._password)
except Exception as e:
print(f"Failed to connect to SMTP server: {e}")
raise
def _quit(self) -> None:
try:
self._server.quit()
except Exception as e:
print(f"Failed to disconnect from SMTP server: {e}")
def send_message(
self,
from_address: str,
to_address: str,
subject: str = "No subject",
message: str = "",
) -> None:
try:
print("Preparing email message...")
msg = MIMEMultipart()
msg["From"] = from_address
if not to_address:
to_address = self.to_address
msg["To"] = to_address
msg["Subject"] = subject
mime = MIMEText(
message,
"html" if message.lower().startswith("<!doctype html>") else "plain",
)
msg.attach(mime)
print("Connecting to server to send email...")
self._connect()
print(f"Sending email to {to_address}...")
self._server.sendmail(from_address, to_address, msg.as_string())
print("Email sent successfully.")
except Exception as e:
print(f"Failed to send email: {e}")
finally:
print("Disconnecting from SMTP server...")
self._quit()
# Main Function to Test the Email Client with Gmail
if __name__ == "__main__":
# Gmail Configuration
SMTP_HOST = "smtp.gmail.com"
SMTP_PORT = 587
LOGIN = "[email protected]" # Replace with your Gmail address
PASSWORD = "sadfsfsdfdsdsfsdfdsfsd" # Replace with your App Password generated in Gmail
# Create a concrete SMTP server instance
smtp_server = SmtpLibEmailServer(SMTP_HOST, SMTP_PORT)
# Create an email client with the SMTP server
email_client = EmailClient(smtp_server, login=LOGIN, password=PASSWORD)
# Send a message using the email client
try:
email_client.send_message(
from_address="[email protected]", # Replace with your Gmail address
to_address="[email protected]", # Replace with the recipient's email address
subject="Test Email",
message="This is a test email sent via Gmail SMTP."
)
except Exception as e:
print(f"An error occurred while sending the email: {e}")