ezKit 1.7.1__py3-none-any.whl → 1.7.2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
ezKit/sendemail.py CHANGED
@@ -1,29 +1,62 @@
1
- '''
2
- https://stackoverflow.com/questions/882712/sending-html-email-using-python
3
- '''
1
+ """
2
+ 发送邮件
3
+ """
4
+ # https://stackoverflow.com/questions/882712/sending-html-email-using-python
5
+ # pylint: disable=E0611
6
+ # pylint: disable=R0911
7
+ # pylint: disable=R0912
8
+ # pylint: disable=R0913
9
+ # pylint: disable=R0914
10
+ # pylint: disable=R0915
11
+ # pylint: disable=R1710
4
12
  import smtplib
5
13
  from email.header import Header
6
14
  from email.mime.image import MIMEImage
7
15
  from email.mime.multipart import MIMEMultipart
8
16
  from email.mime.text import MIMEText
9
17
  from email.utils import formataddr, parseaddr
18
+ from typing import Optional, TypedDict, cast
10
19
 
11
20
  from loguru import logger
12
21
 
13
22
  from . import utils
14
23
 
15
24
 
25
+ class TypedSMTP(TypedDict):
26
+ """smtp type"""
27
+ server: str
28
+ port: int
29
+ tls: bool
30
+
31
+ class TypedSender(TypedDict):
32
+ """sender type"""
33
+ name: str
34
+ address: str
35
+ password: str
36
+
37
+ class TypedBody(TypedDict, total=False):
38
+ """body type"""
39
+ content: str
40
+ type: Optional[str]
41
+
16
42
  def format_parse(s):
17
43
  _name, _addr = parseaddr(s)
18
- return formataddr((Header(_name, 'utf-8').encode(), _addr))
19
-
20
- def related_html(smtp=None, sender=None, recipients=None, subject=None, html_file=None, images=None):
21
- '''
44
+ return formataddr((Header(_name, "utf-8").encode(), _addr))
45
+
46
+ def sendemail(
47
+ smtp: TypedSMTP,
48
+ sender: TypedSender,
49
+ recipients: str | list,
50
+ subject: str,
51
+ body: TypedBody,
52
+ images: None | list = None
53
+ ) -> bool:
54
+ """
22
55
  smtp SMTP信息
23
56
 
24
- server SMTP地址
25
- port SMTP端口
26
- ssl 是否使用SSL
57
+ server SMTP地址
58
+ port SMTP端口
59
+ tls 是否使用TLS
27
60
 
28
61
  sender 发件人信息
29
62
 
@@ -31,15 +64,20 @@ def related_html(smtp=None, sender=None, recipients=None, subject=None, html_fil
31
64
  address 发件人邮箱地址
32
65
  password 发件人邮箱密码(SMTP)
33
66
 
34
- recipients 收件人列表
35
- subject 邮件主题
36
- html_file HTML文件
67
+ recipients 收件人(或列表)
68
+
69
+ subject 邮件主题
70
+
71
+ body 邮件主体
72
+
73
+ content 内容
74
+ type 类型 (默认 plain, 或者 file, 或者 html)
37
75
 
38
76
  images 图片列表(可选)
39
77
 
40
78
  cid 图片CID
41
79
  path 图片路径
42
- '''
80
+ """
43
81
 
44
82
  # 参数判断
45
83
  # match True:
@@ -59,88 +97,172 @@ def related_html(smtp=None, sender=None, recipients=None, subject=None, html_fil
59
97
  # logger.error('ERROR!! {} is not string or none'.format('html_file'))
60
98
  # return False
61
99
 
62
- logger.success('sendemail start')
100
+ logger.success("sendemail start")
63
101
 
64
102
  try:
65
103
 
66
- _message = MIMEMultipart('related')
104
+ # 邮件主体
105
+
106
+ if utils.v_true(body, dict) is False:
107
+ logger.error("body error")
108
+ return False
67
109
 
68
- with open(html_file, 'r') as _html_file:
110
+ message: MIMEMultipart = MIMEMultipart()
69
111
 
70
- _message.attach(MIMEText(_html_file.read(), 'html', 'utf-8'))
112
+ body_content = cast(str, body.get("content"))
71
113
 
72
- if utils.v_true(images, list):
114
+ if utils.v_true(body_content, str) is False:
115
+ logger.error(f"body content error: {body_content}")
116
+ return False
73
117
 
74
- for _image in images:
118
+ body_type = cast(str, body.get("type"))
75
119
 
76
- try:
120
+ # 从文本文件读取内容
121
+ if body_type == "file":
122
+ with open(body_content, "r", encoding="utf-8") as file:
123
+ message.attach(MIMEText(file.read(), "plain", "utf-8"))
77
124
 
78
- if utils.check_file_type(_image.get('path', ''), 'file'):
125
+ # 从HTML文件读取内容
126
+ elif body_type == "html":
127
+ message = MIMEMultipart("related")
128
+ with open(body_content, "r", encoding="utf-8") as file:
129
+ message.attach(MIMEText(file.read(), "html", "utf-8"))
79
130
 
80
- '''
81
- 添加图片
82
- with open(image_path, 'rb') as image_file:
83
- mime_image = MIMEImage(image_file.read())
84
- # Define the image's ID as referenced above
85
- mime_image.add_header('Content-ID', '<CID>')
86
- message.attach(mime_image)
87
- '''
131
+ # 纯文本内容
132
+ else:
133
+ message.attach(MIMEText(body_content, "plain", "utf-8"))
88
134
 
89
- with open(_image['path'], 'rb') as _image_file:
90
- _mime_image = MIMEImage(_image_file.read())
91
- _mime_image.add_header('Content-ID', '<{}>'.format(_image['cid']))
92
- _message.attach(_mime_image)
135
+ # ------------------------------------------------------------------------------------------
93
136
 
94
- else:
137
+ # SMTP
95
138
 
96
- next
139
+ if utils.v_true(smtp, dict) is False:
140
+ logger.error("smtp error")
141
+ return False
97
142
 
98
- except Exception as e:
99
- logger.exception(e)
100
- next
143
+ smtp_host = cast(str, smtp.get("server"))
144
+ smtp_port = cast(int, smtp.get("port"))
145
+ smtp_tls = cast(bool, smtp.get("tls"))
101
146
 
102
- # 发件人
103
- _message['From'] = formataddr([sender.get('name'), sender.get('address')])
147
+ if utils.v_true(smtp_host, str) is False:
148
+ logger.error(f"smtp host error: {smtp_host}")
149
+ return False
150
+
151
+ if utils.v_true(smtp_port, int) is False:
152
+ logger.error(f"smtp port error: {smtp_port}")
153
+ return False
154
+
155
+ smtp_tls = utils.v_true(smtp_tls, bool)
156
+
157
+ # ------------------------------------------------------------------------------------------
158
+
159
+ # 发件人信息
160
+
161
+ if utils.v_true(sender, dict) is False:
162
+ logger.error("sender error")
163
+ return False
164
+
165
+ sender_name = cast(str, sender.get("name"))
166
+ sender_address = cast(str, sender.get("address"))
167
+ sender_password = cast(str, sender.get("password"))
168
+
169
+ if utils.v_true(sender_name, str) is False:
170
+ logger.error(f"sender name error: {sender_name}")
171
+ return False
172
+
173
+ if utils.v_true(sender_address, str) is False:
174
+ logger.error(f"sender address error: {sender_address}")
175
+ return False
176
+
177
+ if utils.v_true(sender_password, str) is False:
178
+ logger.error(f"sender password error: {sender_password}")
179
+ return False
180
+
181
+ message["From"] = formataddr((sender_name, sender_address))
182
+
183
+ # ------------------------------------------------------------------------------------------
184
+
185
+ # 收件人(或列表)
104
186
 
105
- # 收件人
106
187
  if utils.v_true(recipients, str):
107
- _message['To'] = format_parse(recipients)
188
+ message["To"] = format_parse(recipients)
108
189
  elif utils.v_true(recipients, list):
109
- _message['To'] = ", ".join(list(map(format_parse, recipients)))
190
+ message["To"] = ", ".join(list(map(format_parse, recipients)))
110
191
  else:
111
- logger.error('recipients error')
192
+ logger.error("recipients error")
112
193
  return False
113
194
 
114
- # 主题
115
- _message['Subject'] = subject
195
+ # ------------------------------------------------------------------------------------------
116
196
 
117
- '''
118
- 发送邮件
197
+ # 邮件主题
119
198
 
120
- SMTP.sendmail(from_addr, to_addrs, msg, mail_options=(), rcpt_options=())
199
+ if utils.v_true(subject, str) is False:
200
+ logger.error("subject error")
201
+ return False
121
202
 
122
- to_addrs = sender_to + sender_cc
123
- https://docs.python.org/3/library/smtplib.html#smtplib.SMTP.sendmail
124
- https://gist.github.com/AO8/c5a6f747eeeca02351152ae8dc79b537
125
- '''
203
+ message["Subject"] = subject
126
204
 
127
- if smtp.get('ssl', False) == True:
205
+ # ------------------------------------------------------------------------------------------
128
206
 
129
- with smtplib.SMTP_SSL(smtp.get('server'), smtp.get('port')) as _smtp:
130
- _smtp.login(sender.get('address'), sender.get('password'))
131
- _smtp.sendmail(sender.get('address'), recipients, _message.as_string())
207
+ if images is not None and utils.v_true(images, list):
132
208
 
133
- else:
209
+ for image in images:
210
+
211
+ try:
212
+
213
+ if utils.check_file_type(image.get("path", ""), "file"):
134
214
 
135
- with smtplib.SMTP(smtp.get('server'), smtp.get('port')) as _smtp:
136
- _smtp.login(sender.get('address'), sender.get('password'))
137
- _smtp.sendmail(sender.get('address'), recipients, _message.as_string())
215
+ # 添加图片
216
+ # with open(image_path, "rb") as image_file:
217
+ # mime_image = MIMEImage(image_file.read())
218
+ # # Define the image's ID as referenced above
219
+ # mime_image.add_header("Content-ID", "<CID>")
220
+ # message.attach(mime_image)
138
221
 
139
- logger.success('sendemail success')
222
+ with open(image["path"], "rb") as _image_file:
223
+ mime_image = MIMEImage(_image_file.read())
224
+ mime_image.add_header("Content-ID", f"<{image['cid']}>")
225
+ message.attach(mime_image)
140
226
 
141
- return True
227
+ except Exception as e:
228
+ logger.exception(e)
229
+ return False
230
+
231
+ # ------------------------------------------------------------------------------------------
232
+
233
+ # 发送邮件
234
+
235
+ # SMTP.sendmail(from_addr, to_addrs, msg, mail_options=(), rcpt_options=())
236
+ #
237
+ # to_addrs = sender_to + sender_cc
238
+ # https://docs.python.org/3/library/smtplib.html#smtplib.SMTP.sendmail
239
+ # https://gist.github.com/AO8/c5a6f747eeeca02351152ae8dc79b537
240
+
241
+ # if smtp.get('ssl', False) is True:
242
+
243
+ # with smtplib.SMTP_SSL(smtp_host, smtp_port) as _smtp:
244
+ # _smtp.login(sender_address, sender_password)
245
+ # _smtp.sendmail(sender_address, recipients, _message.as_string())
246
+
247
+ # else:
248
+
249
+ with smtplib.SMTP(smtp_host, smtp_port) as smtp_server:
250
+ if smtp_tls is True:
251
+ smtp_server.starttls()
252
+ smtp_server.login(sender_address, sender_password)
253
+ smtp_server.sendmail(sender_address, recipients, message.as_string())
254
+
255
+ logger.success("sendemail success")
256
+
257
+ return True
142
258
 
143
259
  except Exception as e:
260
+
261
+ # 忽略腾讯邮箱返回的异常
262
+ if e.args == (-1, b'\x00\x00\x00'):
263
+ # pass
264
+ return True
265
+
144
266
  logger.error('sendemail error')
145
267
  logger.exception(e)
146
268
  return False
@@ -1,9 +1,8 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: ezKit
3
- Version: 1.7.1
3
+ Version: 1.7.2
4
4
  Summary: Easy Kit
5
5
  Author: septvean
6
6
  Author-email: septvean@gmail.com
7
7
  Requires-Python: >=3.11
8
8
  License-File: LICENSE
9
-
@@ -10,13 +10,13 @@ ezKit/plots.py,sha256=QUtoVfZ49ZSNcY8gcQ2TYVkMjDDzoW-myMtqTi5WN2U,5322
10
10
  ezKit/qywx.py,sha256=7eWrlTLrUj6U6cViEGbT6_LQxFGVqkhGAefBSS6T_-0,6531
11
11
  ezKit/redis.py,sha256=pY4SPlcgQ7S8IeY2xoDpxy-xCZxzZQrQJNAoWRsC1dI,1773
12
12
  ezKit/reports.py,sha256=dBBggggCCLuk5YD6SjdUPuxTr3wiJojP3lA7dQfg6Pk,8898
13
- ezKit/sendemail.py,sha256=PItznLBcZ6Om8NU7rep69m3QNZ9YkmOovup7pPGyY58,4840
13
+ ezKit/sendemail.py,sha256=AAdxBvEYN_AJVvBkSAvXzhXC5jkbRsD_8P51h2SdTRw,8413
14
14
  ezKit/token.py,sha256=4L6A26KsxvB4WfF8R7SYiBmihJK0PiN5Oh7dgDVJtxU,1382
15
15
  ezKit/utils.py,sha256=VkZzKy_jupr25Axa5I0juMsm1XiaimyiPoSITA91jcg,47826
16
16
  ezKit/xftp.py,sha256=qbCqFcGe22TDBSisj0Zoz78tnydDWoOfvywWpXdfaGw,6982
17
17
  ezKit/zabbix.py,sha256=soM5UEeYMfm7NczbPOVLirmHm3G20dECQ0aCBttZfhQ,28350
18
- ezKit-1.7.1.dist-info/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
19
- ezKit-1.7.1.dist-info/METADATA,sha256=KibjySW6aXShA6YkITs9NwhdMG4LCijMTKcAu7-uT50,164
20
- ezKit-1.7.1.dist-info/WHEEL,sha256=R06PA3UVYHThwHvxuRWMqaGcr-PuniXahwjmQRFMEkY,91
21
- ezKit-1.7.1.dist-info/top_level.txt,sha256=aYLB_1WODsqNTsTFWcKP-BN0KCTKcV-HZJ4zlHkCFw8,6
22
- ezKit-1.7.1.dist-info/RECORD,,
18
+ ezKit-1.7.2.dist-info/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
19
+ ezKit-1.7.2.dist-info/METADATA,sha256=9UQXveHgueN-AAoB54mCK8fgexmupSvLrO7UoCWbOMo,163
20
+ ezKit-1.7.2.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
21
+ ezKit-1.7.2.dist-info/top_level.txt,sha256=aYLB_1WODsqNTsTFWcKP-BN0KCTKcV-HZJ4zlHkCFw8,6
22
+ ezKit-1.7.2.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (75.5.0)
2
+ Generator: setuptools (75.6.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
File without changes