simtoolsz 0.2.0__tar.gz → 0.2.2__tar.gz

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.
Files changed (31) hide show
  1. {simtoolsz-0.2.0 → simtoolsz-0.2.2}/PKG-INFO +1 -1
  2. {simtoolsz-0.2.0 → simtoolsz-0.2.2}/pyproject.toml +1 -1
  3. {simtoolsz-0.2.0 → simtoolsz-0.2.2}/src/simtoolsz/__init__.py +1 -1
  4. {simtoolsz-0.2.0 → simtoolsz-0.2.2}/src/simtoolsz/mail.py +30 -13
  5. simtoolsz-0.2.2/tests/verify_unicode_fix.py +93 -0
  6. {simtoolsz-0.2.0 → simtoolsz-0.2.2}/.github/workflows/publish.yml +0 -0
  7. {simtoolsz-0.2.0 → simtoolsz-0.2.2}/.gitignore +0 -0
  8. {simtoolsz-0.2.0 → simtoolsz-0.2.2}/.python-version +0 -0
  9. {simtoolsz-0.2.0 → simtoolsz-0.2.2}/LICENSE +0 -0
  10. {simtoolsz-0.2.0 → simtoolsz-0.2.2}/README.md +0 -0
  11. {simtoolsz-0.2.0 → simtoolsz-0.2.2}/README_EN.md +0 -0
  12. {simtoolsz-0.2.0 → simtoolsz-0.2.2}/docs/DATETIME_CONVERSION.md +0 -0
  13. {simtoolsz-0.2.0 → simtoolsz-0.2.2}/docs/mail_usage_guide.md +0 -0
  14. {simtoolsz-0.2.0 → simtoolsz-0.2.2}/examples/conversion_examples.py +0 -0
  15. {simtoolsz-0.2.0 → simtoolsz-0.2.2}/examples/mail_examples.py +0 -0
  16. {simtoolsz-0.2.0 → simtoolsz-0.2.2}/examples/today_examples.py +0 -0
  17. {simtoolsz-0.2.0 → simtoolsz-0.2.2}/examples/zip2db_example.py +0 -0
  18. {simtoolsz-0.2.0 → simtoolsz-0.2.2}/requirements-dev.lock +0 -0
  19. {simtoolsz-0.2.0 → simtoolsz-0.2.2}/requirements.lock +0 -0
  20. {simtoolsz-0.2.0 → simtoolsz-0.2.2}/src/simtoolsz/datetime.py +0 -0
  21. {simtoolsz-0.2.0 → simtoolsz-0.2.2}/src/simtoolsz/io.py +0 -0
  22. {simtoolsz-0.2.0 → simtoolsz-0.2.2}/src/simtoolsz/utils.py +0 -0
  23. {simtoolsz-0.2.0 → simtoolsz-0.2.2}/src/simtoolsz/youtube.py +0 -0
  24. {simtoolsz-0.2.0 → simtoolsz-0.2.2}/tests/test_conversion.py +0 -0
  25. {simtoolsz-0.2.0 → simtoolsz-0.2.2}/tests/test_iso_comprehensive.py +0 -0
  26. {simtoolsz-0.2.0 → simtoolsz-0.2.2}/tests/test_iso_format.py +0 -0
  27. {simtoolsz-0.2.0 → simtoolsz-0.2.2}/tests/test_simple.py +0 -0
  28. {simtoolsz-0.2.0 → simtoolsz-0.2.2}/tests/test_today_optimized.py +0 -0
  29. {simtoolsz-0.2.0 → simtoolsz-0.2.2}/tests/test_which_format.py +0 -0
  30. {simtoolsz-0.2.0 → simtoolsz-0.2.2}/tests/test_zip2db.py +0 -0
  31. {simtoolsz-0.2.0 → simtoolsz-0.2.2}/tests/test_zip2db_simple.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: simtoolsz
3
- Version: 0.2.0
3
+ Version: 0.2.2
4
4
  Summary: A simple tool collection.
5
5
  Author-email: Sidney Zhang <liangyi@me.com>
6
6
  License: MulanPSL-2.0
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "simtoolsz"
3
- version = "0.2.0"
3
+ version = "0.2.2"
4
4
  description = "A simple tool collection."
5
5
  keywords = ["tool", "collection"]
6
6
  license = { text = "MulanPSL-2.0" }
@@ -9,7 +9,7 @@ import simtoolsz.datetime as datetime
9
9
  try:
10
10
  __version__ = importlib.metadata.version("simtoolsz")
11
11
  except importlib.metadata.PackageNotFoundError:
12
- __version__ = "0.2.0"
12
+ __version__ = "0.2.2"
13
13
 
14
14
  __all__ = [
15
15
  '__version__', 'mail', 'utils', 'datetime', 'io'
@@ -137,8 +137,11 @@ def send_email(
137
137
 
138
138
  # 设置发件人
139
139
  if sender_name:
140
- sender_name = Header(sender_name, "utf-8").encode()
141
- msg["From"] = formataddr((sender_name, email_account)) if sender_name else email_account
140
+ # 使用Header处理非ASCII字符,然后手动格式化地址
141
+ encoded_name = Header(sender_name, "utf-8").encode()
142
+ msg["From"] = f"{encoded_name} <{email_account}>"
143
+ else:
144
+ msg["From"] = email_account
142
145
 
143
146
  def format_recipient_list(recipient_list):
144
147
  """格式化收件人列表"""
@@ -146,8 +149,12 @@ def send_email(
146
149
  for recipient in recipient_list:
147
150
  if isinstance(recipient, tuple) and len(recipient) == 2:
148
151
  name, addr = recipient
149
- name = Header(name, "utf-8").encode()
150
- formatted.append(formataddr((name, addr)))
152
+ if name:
153
+ # 使用Header处理非ASCII字符,然后手动格式化地址
154
+ encoded_name = Header(name, "utf-8").encode()
155
+ formatted.append(f"{encoded_name} <{addr}>")
156
+ else:
157
+ formatted.append(addr)
151
158
  else:
152
159
  # 处理字符串格式如 "张三<user@example.com>"
153
160
  recipient_str = str(recipient)
@@ -155,8 +162,9 @@ def send_email(
155
162
  name_part = recipient_str.split("<")[0].strip()
156
163
  addr_part = recipient_str.split("<")[1].split(">")[0].strip()
157
164
  if name_part:
158
- name_part = Header(name_part, "utf-8").encode()
159
- formatted.append(formataddr((name_part, addr_part)))
165
+ # 使用Header处理非ASCII字符,然后手动格式化地址
166
+ encoded_name = Header(name_part, "utf-8").encode()
167
+ formatted.append(f"{encoded_name} <{addr_part}>")
160
168
  else:
161
169
  formatted.append(addr_part)
162
170
  else:
@@ -165,9 +173,15 @@ def send_email(
165
173
 
166
174
  # 设置收件人
167
175
  msg["Subject"] = Header(subject, "utf-8")
168
- msg["To"] = ", ".join(format_recipient_list(all_recipients))
176
+
177
+ # 处理收件人,确保正确编码
178
+ if all_recipients:
179
+ formatted_recipients = format_recipient_list(all_recipients)
180
+ msg["To"] = ", ".join(formatted_recipients)
181
+
169
182
  if all_cc:
170
- msg["Cc"] = ", ".join(format_recipient_list(all_cc))
183
+ formatted_cc = format_recipient_list(all_cc)
184
+ msg["Cc"] = ", ".join(formatted_cc)
171
185
 
172
186
  # 处理邮件正文和签名
173
187
  full_content = content
@@ -202,8 +216,9 @@ def send_email(
202
216
  _, subtype = mime_type.split("/", 1)
203
217
  img_part = MIMEImage(img_data, _subtype=subtype)
204
218
  img_part.add_header("Content-ID", f"<{cid}>")
205
- img_part.add_header("Content-Disposition", "inline",
206
- filename=Header(img_path.name, "utf-8").encode())
219
+ # 正确处理内嵌图片文件名编码
220
+ encoded_filename = Header(img_path.name, "utf-8").encode()
221
+ img_part.add_header("Content-Disposition", "inline", filename=encoded_filename)
207
222
  msg.attach(img_part)
208
223
  except Exception as e:
209
224
  raise RuntimeError(f"处理内嵌图片失败 {img_path}: {e}")
@@ -218,9 +233,10 @@ def send_email(
218
233
  with open(file_path, "rb") as f:
219
234
  file_data = f.read()
220
235
 
221
- part = MIMEApplication(file_data, Name=Header(file_path.name, "utf-8").encode())
222
- part.add_header("Content-Disposition", "attachment",
223
- filename=Header(file_path.name, "utf-8").encode())
236
+ # 正确处理附件文件名编码
237
+ encoded_filename = Header(file_path.name, "utf-8").encode()
238
+ part = MIMEApplication(file_data, Name=encoded_filename)
239
+ part.add_header("Content-Disposition", "attachment", filename=encoded_filename)
224
240
  msg.attach(part)
225
241
  except Exception as e:
226
242
  raise RuntimeError(f"处理附件失败 {file_path}: {e}")
@@ -277,6 +293,7 @@ def send_email(
277
293
  server.starttls()
278
294
 
279
295
  # 登录并发送
296
+ server.local_hostname = 'Localhost'
280
297
  server.login(email_account, password)
281
298
  server.sendmail(email_account, all_emails, msg.as_string())
282
299
  server.quit()
@@ -0,0 +1,93 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ """
4
+ 邮件Unicode编码修复验证脚本
5
+
6
+ 这个脚本验证修复的邮件发送功能是否能正确处理包含中文和其他
7
+ 非ASCII字符的情况,避免'ascii' codec编码错误。
8
+ """
9
+
10
+ import sys
11
+ import os
12
+ sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'src'))
13
+
14
+ from simtoolsz.mail import send_email
15
+
16
+ def test_unicode_email_sending():
17
+ """测试Unicode字符邮件发送修复"""
18
+ print("=== 邮件Unicode编码修复验证 ===\n")
19
+
20
+ test_cases = [
21
+ {
22
+ "name": "中文发件人和收件人",
23
+ "sender_name": "张三",
24
+ "recipients": ["李四<recipient@example.com>"],
25
+ "subject": "中文主题测试",
26
+ "content": "这是一封包含中文内容的测试邮件。"
27
+ },
28
+ {
29
+ "name": "混合字符测试",
30
+ "sender_name": "Admin管理员",
31
+ "recipients": ["Test用户<recipient@example.com>"],
32
+ "subject": "Mixed Test 混合测试",
33
+ "content": "This email contains both English and 中文内容 for testing."
34
+ }
35
+ ]
36
+
37
+ all_passed = True
38
+
39
+ for i, test_case in enumerate(test_cases, 1):
40
+ print(f"测试 {i}: {test_case['name']}")
41
+
42
+ try:
43
+ result = send_email(
44
+ email_account="test@example.com",
45
+ password="test123",
46
+ subject=test_case['subject'],
47
+ content=test_case['content'],
48
+ recipients=test_case['recipients'],
49
+ sender_name=test_case['sender_name'],
50
+ smtp_config={
51
+ "smtp_server": "smtp.example.com",
52
+ "port": 587,
53
+ "use_ssl": False
54
+ },
55
+ timeout=3 # 短超时,因为我们只测试编码不实际发送
56
+ )
57
+
58
+ # 检查是否出现ASCII编码错误
59
+ error_msg = result['message'].lower()
60
+ if "ascii" in error_msg and "codec" in error_msg:
61
+ print(f"❌ ASCII编码错误仍然存在: {result['message']}")
62
+ all_passed = False
63
+ else:
64
+ print(f"✅ Unicode编码处理正常")
65
+ print(f" 消息: {result['message']}")
66
+
67
+ except UnicodeEncodeError as e:
68
+ print(f"❌ Unicode编码错误: {e}")
69
+ all_passed = False
70
+ except Exception as e:
71
+ # 其他错误(如网络连接失败)是可以接受的,因为我们没有真实的服务器
72
+ error_msg = str(e).lower()
73
+ if "ascii" in error_msg and "codec" in error_msg:
74
+ print(f"❌ ASCII编码错误: {e}")
75
+ all_passed = False
76
+ else:
77
+ print(f"✅ 无编码错误(其他错误可接受): {e}")
78
+
79
+ print()
80
+
81
+ return all_passed
82
+
83
+ if __name__ == "__main__":
84
+ success = test_unicode_email_sending()
85
+
86
+ if success:
87
+ print("🎉 邮件Unicode编码修复验证通过!")
88
+ print("修复成功解决了 'ascii' codec can't encode characters 错误。")
89
+ else:
90
+ print("❌ 邮件Unicode编码修复验证失败。")
91
+ print("仍然存在编码问题,需要进一步修复。")
92
+
93
+ sys.exit(0 if success else 1)
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes