UtilityLibAPI 0.1.1__tar.gz → 1.2510.21__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: UtilityLibAPI
3
- Version: 0.1.1
3
+ Version: 1.2510.21
4
4
  Summary: UtilityLibAPI Python package
5
5
  Author-email: James Lin <tylin123@ms27.hinet.net>
6
6
  License: Copyright (c) 2025 James Lin **UtilityLibAPI**
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "UtilityLibAPI"
7
- version = "0.1.1"
7
+ version = "1.2510.21"
8
8
  description = "UtilityLibAPI Python package"
9
9
  authors = [
10
10
  { name="James Lin", email="tylin123@ms27.hinet.net" }
@@ -0,0 +1,192 @@
1
+ import smtplib
2
+ from email.mime.text import MIMEText
3
+ from email.mime.multipart import MIMEMultipart
4
+ from email.mime.application import MIMEApplication
5
+ from email.utils import formataddr
6
+ from typing import List, Optional
7
+ import os
8
+ import mimetypes
9
+
10
+ class CLASS_MailSender:
11
+ def __init__(self,
12
+ Pms_SMTP_Server: str,
13
+ Pmi_Port: int,
14
+ Pms_Account: str,
15
+ Pms_Password: str,
16
+ Pmb_UseSSL: bool = True):
17
+ """
18
+ 初始化郵件寄送物件
19
+ :param Pms_SMTP_Server: 郵件伺服器主機 (ex: smtp.gmail.com)
20
+ :param Pmi_Port: 通訊埠 (SSL=465, TLS=587)
21
+ :param Pms_Account: 登入帳號
22
+ :param Pms_Password: 登入密碼或應用程式密碼
23
+ :param Pmb_UseSSL: 是否使用 SSL 連線 (預設 True)
24
+ """
25
+ self.Pms_SMTP_Server = Pms_SMTP_Server
26
+ self.Pmi_Port = Pmi_Port
27
+ self.Pms_Account = Pms_Account
28
+ self.Pms_Password = Pms_Password
29
+ self.Pmb_UseSSL = Pmb_UseSSL
30
+
31
+ #------------------------------------------------------------
32
+ def CUF_CreateMessage(self,
33
+ Pms_Subject: str,
34
+ Pms_BodyText: str,
35
+ Pms_BodyHTML: Optional[str] = None,
36
+ Pms_From: Optional[str] = None,
37
+ Pobj_To: Optional[List[str]] = None,
38
+ Pobj_Cc: Optional[List[str]] = None,
39
+ Pobj_Bcc: Optional[List[str]] = None,
40
+ Pobj_Attachments: Optional[List[str]] = None) -> MIMEMultipart:
41
+ """
42
+ 建立郵件內容(支援 HTML / 附件)
43
+ """
44
+ msg = MIMEMultipart("alternative")
45
+ msg["From"] = formataddr((Pms_From or self.Pms_Account, self.Pms_Account))
46
+ msg["To"] = ", ".join(Pobj_To or [])
47
+ if Pobj_Cc:
48
+ msg["Cc"] = ", ".join(Pobj_Cc)
49
+ msg["Subject"] = Pms_Subject
50
+
51
+ # 純文字版本
52
+ msg.attach(MIMEText(Pms_BodyText or "", "plain", "utf-8"))
53
+
54
+ # HTML 版本
55
+ if Pms_BodyHTML:
56
+ msg.attach(MIMEText(Pms_BodyHTML, "html", "utf-8"))
57
+
58
+ # 附件
59
+ if Pobj_Attachments:
60
+ for ms_path in Pobj_Attachments:
61
+ try:
62
+ if not os.path.isfile(ms_path):
63
+ print(f"⚠️ Attachements not exists: {ms_path}")
64
+ continue
65
+
66
+ ctype, encoding = mimetypes.guess_type(ms_path)
67
+ if ctype is None or encoding is not None:
68
+ ctype = "application/octet-stream"
69
+ maintype, subtype = ctype.split("/", 1)
70
+
71
+ with open(ms_path, "rb") as f:
72
+ part = MIMEApplication(f.read(), _subtype=subtype)
73
+ filename = os.path.basename(ms_path)
74
+ part.add_header(
75
+ "Content-Disposition",
76
+ "attachment",
77
+ filename=("utf-8", "", filename)
78
+ )
79
+ msg.attach(part)
80
+ except Exception as e:
81
+ print(f"⚠️ Can not add attachment: {ms_path} ({e})")
82
+
83
+ return msg
84
+
85
+ #------------------------------------------------------------
86
+ def CUF_SendMail(self,
87
+ Pms_Subject: str,
88
+ Pms_BodyText: str,
89
+ Pms_BodyHTML: Optional[str],
90
+ Pobj_To: List[str],
91
+ Pobj_Cc: Optional[List[str]] = None,
92
+ Pobj_Bcc: Optional[List[str]] = None,
93
+ Pobj_Attachments: Optional[List[str]] = None) -> bool:
94
+ """
95
+ 實際寄送郵件
96
+ """
97
+ msg = self.CUF_CreateMessage(
98
+ Pms_Subject=Pms_Subject,
99
+ Pms_BodyText=Pms_BodyText,
100
+ Pms_BodyHTML=Pms_BodyHTML,
101
+ Pobj_To=Pobj_To,
102
+ Pobj_Cc=Pobj_Cc,
103
+ Pobj_Bcc=Pobj_Bcc,
104
+ Pobj_Attachments=Pobj_Attachments,
105
+ )
106
+
107
+ all_recipients = (Pobj_To or []) + (Pobj_Cc or []) + (Pobj_Bcc or [])
108
+
109
+ try:
110
+ if self.Pmb_UseSSL:
111
+ with smtplib.SMTP_SSL(self.Pms_SMTP_Server, self.Pmi_Port) as server:
112
+ server.login(self.Pms_Account, self.Pms_Password)
113
+ server.sendmail(self.Pms_Account, all_recipients, msg.as_string())
114
+ else:
115
+ with smtplib.SMTP(self.Pms_SMTP_Server, self.Pmi_Port) as server:
116
+ server.ehlo()
117
+ server.starttls()
118
+ server.login(self.Pms_Account, self.Pms_Password)
119
+ server.sendmail(self.Pms_Account, all_recipients, msg.as_string())
120
+
121
+ print("✅ Send Success!")
122
+ return True
123
+ except Exception as e:
124
+ print("❌ Failure:", e)
125
+ return False
126
+
127
+
128
+ # ================================================================================
129
+ # [範例]
130
+ # 匯入剛才寫好的 CLASS_MailSender
131
+ #from MailSender import CLASS_MailSender # 假設你把上面的 class 儲存為 MailSender.py
132
+ if __name__ == "__main__":
133
+ # === 初始化郵件傳送物件 ===
134
+ mailer = CLASS_MailSender(
135
+ Pms_SMTP_Server="msr.xxxx.net",
136
+ Pmi_Port=465,
137
+ Pms_Account="xxx.biz@xx.hxxxt.net",
138
+ Pms_Password="xxxxx*",
139
+ Pmb_UseSSL=True
140
+ )
141
+
142
+ # === 郵件收件者設定 ===
143
+ ml_To = ["gt504@gxxxxxh.biz", "txxxxx@ms27.xxxt.net"]
144
+ ml_Cc = ["ebooxxx3@hotmail.com.tw"]
145
+ ml_Bcc = ["xxxxsty.lin@xxx.hinet.net"] # 密件副本,不會顯示在郵件中
146
+
147
+ # === 郵件主題與內容 ===
148
+ ms_Subject = "團隊週報通知"
149
+
150
+ ms_BodyText = """
151
+ 這是一封自動寄出的團隊週報通知。
152
+ 請參閱附加的 PDF 檔或 HTML 內文。
153
+ """
154
+
155
+ ms_BodyHTML = """
156
+ <html>
157
+ <body style="font-family: Microsoft JhengHei;">
158
+ <h2 style="color: green;">🌟 團隊週報</h2>
159
+ <p>各位同仁您好:</p>
160
+ <p>以下為本週重點摘要:</p>
161
+ <ul>
162
+ <li>完成模組 A 測試</li>
163
+ <li>修正 ERP 匯出問題</li>
164
+ <li>新增客戶報表功能</li>
165
+ </ul>
166
+ <p>詳細報表請參閱附件。</p>
167
+ <p style="color: gray;">系統自動寄出,請勿回覆。</p>
168
+ </body>
169
+ </html>
170
+ """
171
+
172
+ # === 附件路徑 ===
173
+ ml_Attachments = [
174
+ "X:\\TEMP\\BOOK\\RCR6000_匯出外部資料_RCR6000EXT_XXX.pdf",
175
+ "X:\\TEMP\\BOOK\\K9AKW4.jpg"
176
+ ]
177
+
178
+ # === 寄送 ===
179
+ mb_OK = mailer.CUF_SendMail(
180
+ Pms_Subject=ms_Subject,
181
+ Pms_BodyText=ms_BodyText,
182
+ Pms_BodyHTML=ms_BodyHTML,
183
+ Pobj_To=ml_To,
184
+ Pobj_Cc=ml_Cc,
185
+ Pobj_Bcc=ml_Bcc,
186
+ Pobj_Attachments=ml_Attachments
187
+ )
188
+
189
+ if mb_OK:
190
+ print("✅ 多人郵件已成功寄出!")
191
+ else:
192
+ print("❌ 寄送失敗,請檢查設定。")
@@ -1,6 +1,8 @@
1
1
  from .EnDeCodeLib import CLASS_EnDeCodeLib
2
2
  from .SessionVARLib import CLASS_SessionVAR
3
+ from .SendMailLib import CLASS_SendMail
3
4
 
4
5
  __all__ = ["CLASS_EnDeCodeLib",
5
- "CLASS_SessionVAR"
6
+ "CLASS_SessionVAR",
7
+ "CLASS_MailSender"
6
8
  ]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: UtilityLibAPI
3
- Version: 0.1.1
3
+ Version: 1.2510.21
4
4
  Summary: UtilityLibAPI Python package
5
5
  Author-email: James Lin <tylin123@ms27.hinet.net>
6
6
  License: Copyright (c) 2025 James Lin **UtilityLibAPI**
@@ -3,6 +3,7 @@ README.md
3
3
  pyproject.toml
4
4
  setup.cfg
5
5
  src/UtilityLibAPI/EnDeCodeLib.py
6
+ src/UtilityLibAPI/MailSenderLib.py
6
7
  src/UtilityLibAPI/SessionVARLib.py
7
8
  src/UtilityLibAPI/__init__.py
8
9
  src/UtilityLibAPI.egg-info/PKG-INFO
File without changes