smartpush 1.3.8__py3-none-any.whl → 1.4.0__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.
@@ -60,6 +60,7 @@ def update_flow(host_domain, cookies, **kwargs):
60
60
  "Content-Type": "application/json"
61
61
  }
62
62
  kwargs["update_flow_params"]["version"] = kwargs.get("version", kwargs["update_flow_params"]["version"])
63
+ kwargs["update_flow_params"]["id"] = kwargs.get("flow_id", kwargs["update_flow_params"]["id"])
63
64
  params = kwargs["update_flow_params"]
64
65
  result = requests.request(method="post", url=_url, headers=headers, json=params).text
65
66
 
@@ -98,33 +99,55 @@ def mock_pulsar(mock_domain, pulsar, limit=1):
98
99
  return json.loads(result)
99
100
 
100
101
 
101
- def check_flow(mock_domain, host_domain, cookies, **kwargs):
102
+ def check_flow(host_domain, cookies, mock_domain="", **kwargs):
102
103
  """
104
+ 完整触发流程
103
105
  params
104
106
  mock_domain:必填,触发接口域名
105
107
  host_domain:必填,spflow接口域名
106
108
  cookies:必填,sp登录态
107
109
  flow_id:必填
108
110
  pulsar:必填,模拟的触发数据
111
+ old_flow_counts: 默认为all,需拆分步骤时填写,枚举:all、one、two;
112
+ one:获取旧节点数据和触发;
113
+ two:获取触发后数据和断言节点数据
114
+
109
115
  limit:非必填,默认为1 - mock_pulsar函数用于控制模拟触发的次数
110
- num:非必填,默认为1 - compare_lists函数用于断言方法做差值计算
116
+ sleep_time: 非必填, 默认60s, 等待时间,用于触发后等待各节点计数后获取新数据
111
117
  update_flow_params: 非必填,dict格式,需更新flow时传参,参数结构为sp的saveFlow接口内容
118
+ num:非必填,默认为1 - compare_lists函数用于断言方法做差值计算
119
+ all_key: 非必填,bool,默认false,输入true时,检查指标节点常用5个字段
120
+ check_key: 非必填, 默认只有completedCount, list格式,传入需检查节点的指标key,如:completedCount、skippedCount、openRate等
112
121
  """
113
- # 触发前提取flow数据,后续做对比
114
- old_flow_counts, old_versions = get_current_flow(host_domain=host_domain, cookies=cookies,
115
- flow_id=kwargs["flow_id"])
116
- # 更新flow
117
- if kwargs.get("update_flow_params", False):
118
- update_flow(host_domain=host_domain, cookies=cookies, update_flow_params=kwargs.get("update_flow_params"),
119
- version=old_versions)
120
- # 启动flow
121
- start_flow(host_domain=host_domain, cookies=cookies, flow_id=kwargs["flow_id"], version=old_versions)
122
- # 触发flow
123
- mock_pulsar(mock_domain=mock_domain, pulsar=kwargs["pulsar"], limit=kwargs.get("limit", 1))
124
- # 触发后提取flow数据,做断言
125
- time.sleep(30)
126
- new_flow_counts, new_versions = get_current_flow(host_domain=host_domain, cookies=cookies,
127
- flow_id=kwargs["flow_id"])
128
- # 断言
129
- result = ListDictUtils.compare_lists(temp1=old_flow_counts, temp2=new_flow_counts, num=kwargs.get("num", 1))
130
- return [True, "断言成功"] if len(result) == 0 else [False, result]
122
+ # todo: 还差邮件校验部分,后续补充
123
+ is_split_steps = kwargs.get("split_steps", "all")
124
+ # 步骤1 - 所需字段:split_steps、host_domain、cookies、flow_id、pulsar
125
+ if is_split_steps == "one" or is_split_steps == "all":
126
+ # 触发前提取flow数据,后续做对比
127
+ old_flow_counts, old_versions = get_current_flow(host_domain=host_domain, cookies=cookies,
128
+ flow_id=kwargs["flow_id"])
129
+ kwargs["old_flow_counts"] = old_flow_counts
130
+ # 更新flow
131
+ if kwargs.get("update_flow_params", False):
132
+ update_flow(host_domain=host_domain, cookies=cookies, update_flow_params=kwargs.get("update_flow_params"),
133
+ version=old_versions, flow_id=kwargs["flow_id"])
134
+ # 启动flow
135
+ start_flow(host_domain=host_domain, cookies=cookies, flow_id=kwargs["flow_id"], version=old_versions)
136
+ # 触发flow
137
+ mock_pulsar(mock_domain=mock_domain, pulsar=kwargs["pulsar"], limit=kwargs.get("limit", 1))
138
+ if is_split_steps == "one":
139
+ return old_flow_counts, old_versions
140
+
141
+ # 步骤2
142
+ if is_split_steps == "two" or is_split_steps == "all":
143
+ if is_split_steps == "all":
144
+ time.sleep(kwargs.get("sleep_time", 60))
145
+ # 触发后提取flow数据,做断言
146
+ new_flow_counts, new_versions = get_current_flow(host_domain=host_domain, cookies=cookies,
147
+ flow_id=kwargs["flow_id"])
148
+ # 断言
149
+ result = ListDictUtils.compare_lists(temp1=kwargs.get("old_flow_counts"),
150
+ temp2=new_flow_counts, num=kwargs.get("num", 1),
151
+ check_key=kwargs.get("check_key", ["completedCount"]),
152
+ all_key=kwargs.get("all_key", False))
153
+ return [True, "断言成功"] if len(result) == 0 else [False, result]
smartpush/test.py CHANGED
@@ -1,6 +1,8 @@
1
1
  # -*- codeing = utf-8 -*-
2
2
  # @Time :2025/2/20 00:27
3
3
  # @Author :luzebin
4
+ import json
5
+
4
6
  import pandas as pd
5
7
 
6
8
  from smartpush.export.basic import ExcelExportChecker
@@ -9,8 +11,10 @@ from smartpush.export.basic.ReadExcel import read_excel_and_write_to_dict
9
11
  from smartpush.export.basic.GetOssUrl import get_oss_address_with_retry
10
12
  from smartpush.utils.DataTypeUtils import DataTypeUtils
11
13
  from smartpush.flow import MockFlow
14
+ from smartpush.utils import EmailUtlis
12
15
 
13
16
  if __name__ == '__main__':
17
+ # 导出流程
14
18
  oss1 = "https://cdn.smartpushedm.com/material_ec2/2025-02-26/31c1a577af244c65ab9f9a984c64f3d9/ab%E5%BC%B9%E7%AA%97%E6%B5%8B%E8%AF%952.10%E5%88%9B%E5%BB%BA-%E6%9C%89%E5%85%A8%E9%83%A8%E6%95%B0%E6%8D%AE%E9%94%80%E5%94%AE%E9%A2%9D%E6%98%8E%E7%BB%86%E6%95%B0%E6%8D%AE.xlsx"
15
19
  oss2 = "https://cdn.smartpushedm.com/material_ec2/2025-02-26/31c1a577af244c65ab9f9a984c64f3d9/ab%E5%BC%B9%E7%AA%97%E6%B5%8B%E8%AF%952.10%E5%88%9B%E5%BB%BA-%E6%9C%89%E5%85%A8%E9%83%A8%E6%95%B0%E6%8D%AE%E9%94%80%E5%94%AE%E9%A2%9D%E6%98%8E%E7%BB%86%E6%95%B0%E6%8D%AE.xlsx"
16
20
  # # print(check_excel_all(oss1, oss1))
@@ -37,10 +41,10 @@ if __name__ == '__main__':
37
41
  # errors = ExcelExportChecker.check_field_format(actual_oss=oss1, fileds={0: {5: "time"}}, skiprows=1)
38
42
  # ExcelExportChecker.check_excel_name(actual_oss=oss1, expected_oss=url)
39
43
 
44
+ # flow触发流程
40
45
  _url = "http://sp-go-flow-test.inshopline.com"
41
46
  host_domain = "https://test.smartpushedm.com/api-em-ec2"
42
- cookies = "_ga=GA1.1.88071637.1717860341; _ga_NE61JB8ZM6=GS1.1.1718954972.32.1.1718954972.0.0.0; _ga_Z8N3C69PPP=GS1.1.1723104149.2.0.1723104149.0.0.0; _ga_D2KXR23WN3=GS1.1.1735096783.3.1.1735096812.0.0.0; osudb_lang=; a_lang=zh-hans-cn; osudb_uid=4213785218; osudb_oar=#01#SID0000126BGKWZjG4n42Q2CwFh4CS1WDoQZHTsZddVzHm5AvTJYrgIBGBQYLWO+XpYs47JMugUA6ZpHRvCdRTXw0OLXxpvdGnuT8GZ5qgcuWxiOIUHwdOCKPO9aEBTTB6NWeShMEFpZlU9lLxzcYL6HLlPBHe; osudb_appid=SMARTPUSH; osudb_subappid=1; ecom_http_token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3NDc1MzQzMjYsImp0aSI6IjVlMTMyOWU3LTAwMzItNDIyNS1hY2NmLWFlNDY4ZTUxZDgxMiIsInVzZXJJbmZvIjp7ImlkIjowLCJ1c2VySWQiOiI0MjEzNzg1MjE4IiwidXNlcm5hbWUiOiIiLCJlbWFpbCI6InRlc3RzbWFydDA5NUBnbWFpbC5jb20iLCJ1c2VyUm9sZSI6Im93bmVyIiwicGxhdGZvcm1UeXBlIjo3LCJzdWJQbGF0Zm9ybSI6MSwicGhvbmUiOiIiLCJsYW5ndWFnZSI6InpoLWhhbnMtY24iLCJhdXRoVHlwZSI6IiIsImF0dHJpYnV0ZXMiOnsiY291bnRyeUNvZGUiOiJDTiIsImN1cnJlbmN5IjoiVVNEIiwiY3VycmVuY3lTeW1ib2wiOiJVUyQiLCJkb21haW4iOiJmZWxpeC10Yy5teXNob3BsaW5lc3RnLmNvbSIsImxhbmd1YWdlIjoiZW4iLCJtZXJjaGFudEVtYWlsIjoidGVzdHNtYXJ0MDk1QGdtYWlsLmNvbSIsIm1lcmNoYW50TmFtZSI6ImZlbGl4LXRjIiwicGhvbmUiOiIiLCJzY29wZUNoYW5nZWQiOnRydWUsInN0YWZmTGFuZ3VhZ2UiOm51bGwsInN0YXR1cyI6MiwidGltZXpvbmUiOiJBc2lhL0hvbmdfS29uZyJ9LCJzdG9yZUlkIjoiMTY2NTY2MTA4NDM2MyIsImhhbmRsZSI6ImZlbGl4LXRjIiwiZW52IjoiQ04iLCJzdGUiOiIiLCJ2ZXJpZnkiOiIifSwibG9naW5UaW1lIjoxNzQ0OTQyMzI2NTM0LCJzY29wZSI6WyJlbWFpbC1tYXJrZXQiLCJjb29raWUiLCJzbC1lY29tLWVtYWlsLW1hcmtldC1uZXctdGVzdCIsImVtYWlsLW1hcmtldC1uZXctZGV2LWZzIiwiYXBpLXVjLWVjMiIsImFwaS1zdS1lYzIiLCJhcGktZW0tZWMyIiwiZmxvdy1wbHVnaW4iLCJhcGktc3AtbWFya2V0LWVjMiJdLCJjbGllbnRfaWQiOiJlbWFpbC1tYXJrZXQifQ.rBrzepA8U8ghqLcNGGF4N6s6PXA6v6tJaKVOe5jQdaw; JSESSIONID=0228F95DD250A037C91E0E2927EE2FC7"
43
-
47
+ cookies = "a_lang=zh-hans-cn; ecom_http_token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3NDc3OTMyMzgsImp0aSI6ImU1YWY4ZGE5LTlhMTQtNGY0Yi04NmM5LTNlNzAwZTFjY2RiYyIsInVzZXJJbmZvIjp7ImlkIjowLCJ1c2VySWQiOiI0MjEzNzg1MjQ3IiwidXNlcm5hbWUiOiIiLCJlbWFpbCI6ImZlbGl4LnNoYW9Ac2hvcGxpbmVhcHAuY29tIiwidXNlclJvbGUiOiJvd25lciIsInBsYXRmb3JtVHlwZSI6Nywic3ViUGxhdGZvcm0iOjEsInBob25lIjoiIiwibGFuZ3VhZ2UiOiJ6aC1oYW5zLWNuIiwiYXV0aFR5cGUiOiIiLCJhdHRyaWJ1dGVzIjp7ImNvdW50cnlDb2RlIjoiQ04iLCJjdXJyZW5jeSI6IkpQWSIsImN1cnJlbmN5U3ltYm9sIjoiSlDCpSIsImRvbWFpbiI6InNtYXJ0cHVzaDQubXlzaG9wbGluZXN0Zy5jb20iLCJsYW5ndWFnZSI6ImVuIiwibWVyY2hhbnRFbWFpbCI6ImZlbGl4LnNoYW9Ac2hvcGxpbmUuY29tIiwibWVyY2hhbnROYW1lIjoiU21hcnRQdXNoNF9lYzJf6Ieq5Yqo5YyW5bqX6ZO6IiwicGhvbmUiOiIiLCJzY29wZUNoYW5nZWQiOnRydWUsInN0YWZmTGFuZ3VhZ2UiOiJ6aC1oYW5zLWNuIiwic3RhdHVzIjowLCJ0aW1lem9uZSI6IkFzaWEvTWFjYW8ifSwic3RvcmVJZCI6IjE2NDQzOTU5MjA0NDQiLCJoYW5kbGUiOiJzbWFydHB1c2g0IiwiZW52IjoiQ04iLCJzdGUiOiIiLCJ2ZXJpZnkiOiIifSwibG9naW5UaW1lIjoxNzQ1MjAxMjM4NjA0LCJzY29wZSI6WyJlbWFpbC1tYXJrZXQiLCJjb29raWUiLCJzbC1lY29tLWVtYWlsLW1hcmtldC1uZXctdGVzdCIsImVtYWlsLW1hcmtldC1uZXctZGV2LWZzIiwiYXBpLXVjLWVjMiIsImFwaS1zdS1lYzIiLCJhcGktZW0tZWMyIiwiZmxvdy1wbHVnaW4iLCJhcGktc3AtbWFya2V0LWVjMiJdLCJjbGllbnRfaWQiOiJlbWFpbC1tYXJrZXQifQ.NgpEGF_8BJgTOh1LNz_Is43JBd7uZhyTGQtQq8SOdsc; osudb_appid=SMARTPUSH; osudb_lang=; osudb_oar=#01#SID0000126BLmmyWXDjlSc59ljxo2axjoWExJ1oHkAkRqVtfzm4UUtWvBGvzF6FeTbrvTHmfJLrtJz+Dpthge0dIaJpI2ukTujazNNJbLjZFu9kkuOrtRAXNL02fNqpUb6MwTCNxOnm03YIlfb7X2482UvDm36; osudb_subappid=1; osudb_uid=4213785247; JSESSIONID=8DEE7103CFA4505DF68ECE629B00A0F3"
44
48
 
45
49
  params = {
46
50
  "abandonedOrderId": "c2c4a695a36373f56899b370d0f1b6f2",
@@ -91,8 +95,254 @@ if __name__ == '__main__':
91
95
  "uid": "4603296300",
92
96
  "userId": "1911625831177650177"
93
97
  }
94
- mock_pulsar = MockFlow.check_flow(mock_domain=_url, host_domain=host_domain, cookies=cookies,
95
- flow_id="FLOW6749144046546626518", pulsar=params)
96
- # node_counts, versions = MockFlow.get_current_flow(host_domain=host_domain, cookies=cookies,
98
+ update_flow_params = {"id": "FLOW6941975456855532553", "version": "10", "triggerId": "c1001",
99
+ "templateId": "TEMP6911595896571704333", "showData": False, "flowChange": True, "nodes": [
100
+ {"type": "trigger", "data": {
101
+ "trigger": {"trigger": "c1001", "group": "", "suggestionGroupId": "", "triggerStock": False,
102
+ "completedCount": 4, "skippedCount": 0}, "completedCount": 4, "skippedCount": 0},
103
+ "id": "92d115e7-8a86-439a-8cfb-1aa3ef075edf"}, {"type": "delay", "data": {
104
+ "delay": {"type": "relative", "relativeTime": 0, "relativeUnit": "HOURS", "designatedTime": ""},
105
+ "completedCount": 4}, "id": "e0fc258b-fcfc-421c-b215-8e41638072ca"}, {"type": "sendLetter", "data": {
106
+ "sendLetter": {"id": 367462, "activityTemplateId": 367462, "activityName": "flowActivity_EwEi3d",
107
+ "activityImage": "http://cdn.smartpushedm.com/frontend/smart-push/staging/1644395920444/1744102089665/1744102093754_f99e3703.jpeg",
108
+ "emailName": "A Message from Your Cart", "merchantId": "1644395920444",
109
+ "merchantName": "SmartPush4_ec2_自动化店铺",
110
+ "brandName": "SmartPush4_ec2_自动化店铺 AutoTestName", "currency": "JP¥",
111
+ "activityType": "NORMAL", "activityStatus": "ACTIVE", "createTime": 1745201732286,
112
+ "updateTime": 1745201825819, "createDate": "2025-04-21 10:15:32",
113
+ "updateDate": "2025-04-21 10:17:05", "pickContactPacks": [], "excludeContactPacks": [],
114
+ "customerGroupIds": [], "excludeCustomerGroupIds": [], "pickContactInfos": [],
115
+ "excludeContactInfos": [], "customerGroupInfos": [], "excludeCustomerGroupInfos": [],
116
+ "sender": "SmartPush4_ec2_自动化店铺", "senderDomain": "DEFAULT_DOMAIN", "domainType": 3,
117
+ "receiveAddress": "", "originTemplate": 33,
118
+ "currentJsonSchema": "{\"id\":\"a4a9fba2a\",\"type\":\"Stage\",\"props\":{\"backgroundColor\":\"#EAEDF1\",\"width\":\"600px\",\"fullWidth\":\"normal-width\"},\"children\":[{\"id\":\"84ba788da\",\"type\":\"Header\",\"props\":{\"backgroundColor\":\"#ffffff\",\"borderLeft\":\"1px none #ffffff\",\"borderRight\":\"1px none #ffffff\",\"borderTop\":\"1px none #ffffff\",\"borderBottom\":\"1px none #ffffff\",\"paddingTop\":\"0px\",\"paddingBottom\":\"0px\",\"paddingLeft\":\"0px\",\"paddingRight\":\"0px\",\"cols\":[12]},\"children\":[{\"id\":\"98d909a48\",\"type\":\"Column\",\"props\":{},\"children\":[]}]},{\"id\":\"84ba7bbda\",\"type\":\"Section\",\"props\":{\"backgroundColor\":\"#ffffff\",\"borderLeft\":\"1px none #ffffff\",\"borderRight\":\"1px none #ffffff\",\"borderTop\":\"1px none #ffffff\",\"borderBottom\":\"1px none #ffffff\",\"paddingTop\":\"0px\",\"paddingBottom\":\"0px\",\"paddingLeft\":\"0px\",\"paddingRight\":\"0px\",\"cols\":[12]},\"children\":[{\"id\":\"8cab9aa48\",\"type\":\"Column\",\"props\":{},\"children\":[]}]},{\"id\":\"b8bbabad9\",\"type\":\"Footer\",\"props\":{\"backgroundColor\":\"#ffffff\",\"borderLeft\":\"1px none #ffffff\",\"borderRight\":\"1px none #ffffff\",\"borderTop\":\"1px none #ffffff\",\"borderBottom\":\"1px none #ffffff\",\"paddingTop\":\"0px\",\"paddingBottom\":\"0px\",\"paddingLeft\":\"0px\",\"paddingRight\":\"0px\",\"cols\":[12]},\"children\":[{\"id\":\"b3bcabad7\",\"type\":\"Column\",\"props\":{},\"children\":[{\"id\":\"b39b6a94a\",\"type\":\"Subscribe\",\"props\":{\"content\":\"<p style=\\\"text-align:center;\\\"><span style=\\\"font-size:12px\\\"><span style=\\\"font-family:Arial, Helvetica, sans-serif\\\">在此處輸入聯繫地址,可以讓你的顧客更加信任這封郵件</span></span></p>\"},\"children\":[]}]}]}],\"extend\":{\"version\":\"1.0.0\",\"updateTime\":\"2025-03-18T09:57:40.953Z\"}}",
119
+ "currentHtml": "<!doctype html>\n<html xmlns=\"http://www.w3.org/1999/xhtml\" xmlns:v=\"urn:schemas-microsoft-com:vml\" xmlns:o=\"urn:schemas-microsoft-com:office:office\">\n <head>\n <title></title>\n <!--[if !mso]><!-->\n <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n <!--<![endif]-->\n <meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n <style type=\"text/css\">\n #outlook a { padding:0; }\n body { margin:0;padding:0;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%; }\n table, td { border-collapse:collapse;mso-table-lspace:0pt;mso-table-rspace:0pt; }\n img { border:0;line-height:100%; outline:none;text-decoration:none;-ms-interpolation-mode:bicubic; }\n pre{margin: 0;}p{ display: block;margin:0;}\n </style>\n <!--[if mso]>\n <noscript>\n <xml>\n <o:OfficeDocumentSettings>\n <o:AllowPNG/>\n <o:PixelsPerInch>96</o:PixelsPerInch>\n </o:OfficeDocumentSettings>\n </xml>\n </noscript>\n <![endif]-->\n <!--[if lte mso 11]>\n <style type=\"text/css\">\n .mj-outlook-group-fix { width:100% !important; }\n </style>\n <![endif]-->\n \n <!--[if !mso]><!-->\n <link href=\"https://fonts.googleapis.com/css?family=Ubuntu:300,400,500,700\" rel=\"stylesheet\" type=\"text/css\">\n <style type=\"text/css\">\n @import url(https://fonts.googleapis.com/css?family=Ubuntu:300,400,500,700);\n </style>\n <!--<![endif]-->\n\n \n \n <style type=\"text/css\">\n @media only screen and (min-width:480px) {\n .mj-column-per-100 { width:100% !important; max-width: 100%; }\n }\n </style>\n <style media=\"screen and (min-width:480px)\">\n .moz-text-html .mj-column-per-100 { width:100% !important; max-width: 100%; }\n </style>\n \n \n <style type=\"text/css\">\n \n \n </style>\n <style type=\"text/css\">\n @import url(https://fonts.googleapis.com/css?family=Arvo:400|Bodoni+Moda:400|DM+Sans:400|Poppins:400|Hammersmith+One:400|Libre+Baskerville:400|Lexend+Giga:400|Ubuntu:400|Montserrat:400|Nunito:400|News+Cycle:400|Roboto:400|Oswald:400);@import url(https://fonts.googleapis.com/css?family=Asar:400|Bruno+Ace:400|Cantata+One:400|League+Gothic:400|Long+Cang:400|Lovers+Quarrel:400|Nanum+Gothic+Coding:400|Nanum+Myeongjo:400|Noto+Sans+Kaithi:400|Noto+Sans+Kannada:400|Noto+Sans+Math:400|Noto+Sans+Syloti+Nagri:400|Noto+Serif+JP:400|Playwrite+AT+Guides:400|Saira+Extra+Condensed:400|Tsukimi+Rounded:400|Waiting+for+the+Sunrise:400);h1,\nh2,\nh3,\nh4,\nh5 {\n font-weight: bold;\n margin-bottom: 0;\n}\np {\n margin-top: 0;\n margin-bottom: 0;\n min-height: 1em;\n}\n\nul {\n margin-bottom: 0;\n}\n\nth {\n font-weight: bold;\n}\n\na {\n text-decoration: none;\n}\n\na::-webkit-scrollbar {\n -webkit-appearance: none;\n}\n\na::-webkit-scrollbar:horizontal {\n max-height: 8px;\n}\n\na::-webkit-scrollbar-thumb {\n border-radius: 8px;\n background-color: rgba(0, 0, 0, 0.5);\n}\n\nul,\nol,\ndl {\n margin-top: 16px !important;\n}\n\npre {\n word-break: break-word;\n padding: 0;\n margin: 0;\n white-space: inherit !important;\n}\n\npre p {\n word-break: break-word;\n padding: 0;\n margin: 0;\n color: #000000;\n}\n\nspan[style*='color'] a {\n color: inherit;\n}\n\n.mj-column-no-meida-100{\n width: 100% !important;\n}\n.mj-column-no-meida-50{\n width: 50% !important;\n}\n.mj-column-no-meida-33-333333333333336{\n width: 33.333333333333336% !important;\n}\n.mj-column-no-meida-25{\n width: 25% !important;\n}\n\n.white-nowrap {\n white-space: nowrap !important;\n}\n\n/* 间距 */\n.sp-m-p-0 {\n margin: 0;\n padding: 0;\n}\n\n.nps-content-span a {\n color: inherit !important;\n}.sp-font-12 {\n font-size: 12px !important;\n}\n\n.sp-font-14 {\n font-size: 14px !important;\n}\n\n.sp-font-16 {\n font-size: 16px !important;\n}\n\n.sp-font-18 {\n font-size: 18px !important;\n}\n\n.sp-font-20 {\n font-size: 20px !important;\n}\n\n.sp-font-22 {\n font-size: 22px !important;\n}\n\n.sp-font-24 {\n font-size: 24px !important;\n}\n\n.sp-font-26 {\n font-size: 26px !important;\n}\n\n.sp-font-28 {\n font-size: 28px !important;\n}\n\n.sp-font-30 {\n font-size: 30px !important;\n}\n\n.sp-font-32 {\n font-size: 32px !important;\n}\n\n.sp-font-34 {\n font-size: 34px !important;\n}\n\n.sp-font-36 {\n font-size: 36px !important;\n}\n\n.sp-font-38 {\n font-size: 38px !important;\n}\n\n.sp-font-40 {\n font-size: 40px !important;\n}\n\n.sp-font-42 {\n font-size: 42px !important;\n}\n\n.sp-font-44 {\n font-size: 44px !important;\n}\n\n.sp-font-46 {\n font-size: 46px !important;\n}\n\n.sp-font-48 {\n font-size: 48px !important;\n}\n\n.sp-font-50 {\n font-size: 50px !important;\n}\n\n.sp-font-52 {\n font-size: 52px !important;\n}\n\n.sp-font-54 {\n font-size: 54px !important;\n}\n\n.sp-font-56 {\n font-size: 56px !important;\n}\n\n.sp-font-58 {\n font-size: 58px !important;\n}\n\n.sp-font-60 {\n font-size: 60px !important;\n}\n\n.sp-image-icon {\n width: 50px;\n}\n\n@media only screen and (max-width:600px) {\n\n .sp-font-12 {\n font-size: 12px !important;\n }\n\n .sp-font-14 {\n font-size: 12px !important;\n }\n\n .sp-font-16 {\n font-size: 12px !important;\n }\n\n .sp-font-18 {\n font-size: 13px !important;\n }\n\n .sp-font-20 {\n font-size: 15px !important;\n }\n\n .sp-font-22 {\n font-size: 16px !important;\n }\n\n .sp-font-24 {\n font-size: 18px !important;\n }\n\n .sp-font-26 {\n font-size: 19px !important;\n }\n\n .sp-font-28 {\n font-size: 21px !important;\n }\n\n .sp-font-30 {\n font-size: 22px !important;\n }\n\n .sp-font-32 {\n font-size: 24px !important;\n }\n\n .sp-font-34 {\n font-size: 25px !important;\n }\n\n .sp-font-36 {\n font-size: 27px !important;\n }\n\n .sp-font-38 {\n font-size: 28px !important;\n }\n\n .sp-font-40 {\n font-size: 30px !important;\n }\n\n .sp-font-42 {\n font-size: 31px !important;\n }\n\n .sp-font-44 {\n font-size: 32px !important;\n }\n\n .sp-font-46 {\n font-size: 33px !important;\n }\n\n .sp-font-48 {\n font-size: 34px !important;\n }\n\n .sp-font-50 {\n font-size: 35px !important;\n }\n\n .sp-font-52 {\n font-size: 36px !important;\n }\n\n .sp-font-54 {\n font-size: 37px !important;\n }\n\n .sp-font-56 {\n font-size: 38px !important;\n }\n\n .sp-font-58 {\n font-size: 39px !important;\n }\n\n .sp-font-60 {\n font-size: 40px !important;\n }\n\n .sp-image-icon {\n width: 28px !important;\n }\n\n}@media only screen and (max-width:480px) {\n\n .sp-img-h-1-TwoVertical-11,\n .sp-img-h-1-TwoHorizontalColumns-11 {\n height: 170px !important;\n }\n\n .sp-img-h-1-TwoVertical-23,\n .sp-img-h-1-TwoHorizontalColumns-23 {\n height: 243px !important;\n }\n\n .sp-img-h-1-TwoVertical-34,\n .sp-img-h-1-TwoHorizontalColumns-34 {\n height: 227px !important;\n }\n\n .sp-img-h-1-TwoVertical-43,\n .sp-img-h-1-TwoHorizontalColumns-43 {\n height: 127px !important;\n }\n\n .sp-img-h-1-ThreeHorizontalColumns-11 {\n height: 109px !important;\n }\n\n .sp-img-h-1-ThreeHorizontalColumns-23 {\n height: 163px !important;\n }\n\n .sp-img-h-1-ThreeHorizontalColumns-34 {\n height: 145px !important;\n }\n\n .sp-img-h-1-ThreeHorizontalColumns-43 {\n height: 81px !important;\n }\n\n .sp-img-h-2-TwoVertical-11 {\n height: 164px !important;\n }\n\n .sp-img-h-2-TwoVertical-23 {\n height: 246px !important;\n }\n\n .sp-img-h-2-TwoVertical-34 {\n height: 218px !important;\n }\n\n .sp-img-h-2-TwoVertical-43 {\n height: 123px !important;\n }\n\n .sp-img-h-2-ThreeHorizontalColumns-11,\n .sp-img-h-2-TwoHorizontalColumns-11 {\n height: 76px !important;\n }\n\n .sp-img-h-2-ThreeHorizontalColumns-23,\n .sp-img-h-2-TwoHorizontalColumns-23 {\n height: 113px !important;\n }\n\n .sp-img-h-2-ThreeHorizontalColumns-34,\n .sp-img-h-2-TwoHorizontalColumns-34 {\n height: 101px !important;\n }\n\n .sp-img-h-2-ThreeHorizontalColumns-43,\n .sp-img-h-2-TwoHorizontalColumns-43 {\n height: 57px !important;\n }\n}@media only screen and (min-width: 320px) and (max-width: 599px) {\n .mj-w-50 {\n width: 50% !important;\n max-width: 50%;\n }\n}\n\n@media only screen and (max-width: 480px) {\n .shop-white-mobile {\n width: 100% !important;\n }\n .mj-td-force-100{\n display: inline-block;\n width: 100% !important;\n }\n\n .mj-ImageText-screen {\n width: 100% !important;\n }\n .mj-ImageText-img {\n margin: 0 auto;\n }\n\n .mj-ImageText-margin {\n margin: 0 !important;\n }\n\n .mj-ImageText-margin-zero {\n margin: 0 5px 0 0 !important;\n }\n\n .mj-ImageText-margin-one {\n margin: 0 0 0 5px !important;\n }\n .mj-column-per-50-force {\n width: 50% !important;\n max-width: 50%;\n }\n}\n\n@media only screen and (min-width: 480px) {\n .mj-imagetext-force-100{\n display: inline-block;\n width: 100% !important;\n }\n .mj-column-per-100 {\n width: 100% !important;\n max-width: 100%;\n }\n\n .mj-column-per-50 {\n width: 50% !important;\n max-width: 50%;\n }\n\n .mj-column-per-33-333333333333336 {\n width: 33.333333333333336% !important;\n max-width: 33.333333333333336%;\n }\n\n .mj-column-per-25 {\n width: 25% !important;\n max-width: 25%;\n }\n\n\n .mg-column-per-46-5 {\n width: 46.5% !important;\n max-width: 46.5%;\n }\n\n .mj-AbandonProduct-cloum-align-center {\n align-items: flex-start !important;\n }\n\n\n .mj-OrderInformation-padding-top-220 {\n padding-top: 20px !important;\n }\n\n .mj-OrderInformation-float-left {\n float: left !important;\n }\n}@media only screen and (max-width: 480px) {\n .mt-1{\n margin-top: 1px;\n }\n .mt-2{\n margin-top: 2px;\n }\n .mt-3{\n margin-top: 3px;\n }\n .mt-4{\n margin-top: 4px;\n }\n .mt-5{\n margin-top: 5px;\n }\n .mt-6{\n margin-top: 7px;\n }\n .mt-8{\n margin-top: 9px;\n }\n .mt-10{\n margin-top: 10px;\n }\n\n}\n </style>\n \n </head>\n <body style=\"word-spacing:normal;background-color:#EAEDF1;\">\n \n \n <div\n style=\"background-color:#EAEDF1;\"\n >\n <table className=\"pv-stage\">\n <tbody>\n <tr>\n <td style=\"display:table-column;\"><div style=\"width:1px; height:1px;\"><img style=\"width:1px; height:1px;\" width=\"1\" src=\"${SP_OPEN_EMAIL_URL}\" />\n </div></td>\n </tr>\n </tbody>\n </table><div mso-hide: all; position: fixed; height: 0; max-height: 0; overflow: hidden; font-size: 0; style=\"display:none;\">${emailSubtitle}</div>\n \n <!--[if mso | IE]><table align=\"center\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\" class=\"\" role=\"presentation\" style=\"width:600px;\" width=\"600\" bgcolor=\"#ffffff\" ><tr><td style=\"line-height:0px;font-size:0px;mso-line-height-rule:exactly;\"><![endif]-->\n \n \n <div style=\"background:#ffffff;background-color:#ffffff;margin:0px auto;max-width:600px;\">\n \n <table\n align=\"center\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\" role=\"presentation\" style=\"background:#ffffff;background-color:#ffffff;width:100%;\"\n >\n <tbody>\n <tr>\n <td\n style=\"border-bottom:1px none #ffffff;border-left:1px none #ffffff;border-right:1px none #ffffff;border-top:1px none #ffffff;direction:ltr;font-size:0px;padding:20px 0;padding-bottom:0px;padding-left:0px;padding-right:0px;padding-top:0px;text-align:center;\"\n >\n <!--[if mso | IE]><table role=\"presentation\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\"><tr><td class=\"\" style=\"vertical-align:top;width:598px;\" ><![endif]-->\n \n <div\n class=\"mj-column-per-100 mj-outlook-group-fix\" style=\"font-size:0px;text-align:left;direction:ltr;display:inline-block;vertical-align:top;width:100%;\"\n >\n \n <table\n border=\"0\" cellpadding=\"0\" cellspacing=\"0\" role=\"presentation\" style=\"vertical-align:top;\" width=\"100%\"\n >\n <tbody>\n \n <tr>\n <td\n align=\"left\" style=\"font-size:0px;padding:0;word-break:break-word;\"\n >\n \n <table\n cellpadding=\"0\" cellspacing=\"0\" width=\"100%\" border=\"0\" style=\"color:#000000;font-family:Ubuntu, Helvetica, Arial, sans-serif;font-size:13px;line-height:22px;table-layout:fixed;width:100%;border:none;\"\n >\n <table style=\"margin:0;padding:0;width:100%;table-layout:fixed\" class=\"\" sp-id=\"subscribe-area-b39b6a94a\"><tbody><tr style=\"width:100%\"><td style=\"margin:0;padding:0;width:100%;text-align:center;padding-top:20px;padding-left:20px;padding-right:20px;padding-bottom:20px;background-color:transparent;font-family:arial,helvetica,sans-serif,Arial, Helvetica, sans-serif\" class=\"Subscribe\"><table cellPadding=\"0\" cellSpacing=\"0\" style=\"width:100%\"><tbody><tr><td align=\"center\" class=\"sp-font-16\" valign=\"middle\" style=\"padding-left:10px;padding-right:10px;padding-top:10px;text-align:left;font-size:16px\"><div><p style=\"text-align:center;\"><span style=\"font-size:12px\"><span style=\"font-family:Arial, Helvetica, sans-serif\">在此處輸入聯繫地址,可以讓你的顧客更加信任這封郵件</span></span></p></div></td></tr><tr><td align=\"center\" valign=\"middle\" height=\"20\" style=\"font-size:12px;font-family:arial,helvetica,sans-serif,Arial, Helvetica, sans-serif;padding-left:10px;padding-right:10px;padding-bottom:20px\"></td></tr><div><tr style=\"${hide_logo}\" sp-id=\"subscribe-dom-b39b6a94a\">\n <td class='sp-font-16' style=\"padding-left:20px;padding-right:20px;padding-top:20px;text-align:center;font-size:16px\" >\n <div style=\"border-top: 1px solid #EEF1F6\">\n <img src=\"https://cdn.smartpushedm.com/frontend/smart-push/product/image/1731577171577_83853d55.png\" style=\"padding: 10px;vertical-align: middle;width: 158px;\"alt=\"\" />\n </div>\n <p style=\"color:#343434;font-size:12px\">Providing content services for [[shopName]]</p>\n </td>\n </tr></div></tbody></table></td></tr></tbody></table>\n </table>\n \n </td>\n </tr>\n \n </tbody>\n </table>\n \n </div>\n \n <!--[if mso | IE]></td></tr></table><![endif]-->\n </td>\n </tr>\n </tbody>\n </table>\n \n </div>\n \n \n <!--[if mso | IE]></td></tr></table><![endif]-->\n \n \n </div>\n \n </body>\n</html>\n ",
120
+ "previewJsonSchema": "{\"id\":\"a4a9fba2a\",\"type\":\"Stage\",\"props\":{\"backgroundColor\":\"#EAEDF1\",\"width\":\"600px\",\"fullWidth\":\"normal-width\"},\"children\":[{\"id\":\"84ba788da\",\"type\":\"Header\",\"props\":{\"backgroundColor\":\"#ffffff\",\"borderLeft\":\"1px none #ffffff\",\"borderRight\":\"1px none #ffffff\",\"borderTop\":\"1px none #ffffff\",\"borderBottom\":\"1px none #ffffff\",\"paddingTop\":\"0px\",\"paddingBottom\":\"0px\",\"paddingLeft\":\"0px\",\"paddingRight\":\"0px\",\"cols\":[12]},\"children\":[{\"id\":\"98d909a48\",\"type\":\"Column\",\"props\":{},\"children\":[]}]},{\"id\":\"84ba7bbda\",\"type\":\"Section\",\"props\":{\"backgroundColor\":\"#ffffff\",\"borderLeft\":\"1px none #ffffff\",\"borderRight\":\"1px none #ffffff\",\"borderTop\":\"1px none #ffffff\",\"borderBottom\":\"1px none #ffffff\",\"paddingTop\":\"0px\",\"paddingBottom\":\"0px\",\"paddingLeft\":\"0px\",\"paddingRight\":\"0px\",\"cols\":[12]},\"children\":[{\"id\":\"8cab9aa48\",\"type\":\"Column\",\"props\":{},\"children\":[]}]},{\"id\":\"b8bbabad9\",\"type\":\"Footer\",\"props\":{\"backgroundColor\":\"#ffffff\",\"borderLeft\":\"1px none #ffffff\",\"borderRight\":\"1px none #ffffff\",\"borderTop\":\"1px none #ffffff\",\"borderBottom\":\"1px none #ffffff\",\"paddingTop\":\"0px\",\"paddingBottom\":\"0px\",\"paddingLeft\":\"0px\",\"paddingRight\":\"0px\",\"cols\":[12]},\"children\":[{\"id\":\"b3bcabad7\",\"type\":\"Column\",\"props\":{},\"children\":[{\"id\":\"b39b6a94a\",\"type\":\"Subscribe\",\"props\":{\"content\":\"<p style=\\\"text-align:center;\\\"><span style=\\\"font-size:12px\\\"><span style=\\\"font-family:Arial, Helvetica, sans-serif\\\">在此處輸入聯繫地址,可以讓你的顧客更加信任這封郵件</span></span></p>\"},\"children\":[]}]}]}],\"extend\":{\"version\":\"1.0.0\",\"updateTime\":\"2025-03-18T09:57:40.953Z\"}}",
121
+ "generatedHtml": False,
122
+ "templateUrl": "https://cdn2.smartpushedm.com/material/2021-11-29/d4f96fc873e942a397be708c932bbbe4-自定义排版.png",
123
+ "sendStrategy": "NOW", "totalReceiver": 0, "utmConfigEnable": False,
124
+ "subtitle": "Items in your cart are selling out fast!", "language": "en",
125
+ "languageName": "英语", "timezone": "Asia/Shanghai", "timezoneGmt": "GMT+08:00",
126
+ "type": "FLOW", "relId": "FLOW6941975456855532553",
127
+ "parentId": "TEMP6911595896571704333", "nodeId": "2503b475-ce3e-4906-ab04-0ebc387f0d7e",
128
+ "version": "10", "nodeOrder": 0, "sendType": "EMAIL", "productInfos": [], "blocks": [
129
+ {"domId": "subscribe-dom-b39b6a94a", "blockId": "", "areaId": "", "type": "SP_LOGO",
130
+ "column": 1, "fillStyle": 0, "ratio": ""}], "discountCodes": [], "reviews": [], "awards": [],
131
+ "selectProducts": [], "createSource": "BUILD_ACTIVITY", "contentChange": True,
132
+ "activityChange": False, "imageVersion": "1744102089665", "subActivityList": [],
133
+ "warmupPack": 0, "boosterEnabled": False, "smartSending": False, "boosterCreated": False,
134
+ "gmailPromotion": False, "sendTimeType": "FIXED", "sendTimezone": "B_TIMEZONE",
135
+ "sendTimeDelay": False, "sendOption": 1, "hasUserBlock": False, "hasAutoBlock": False,
136
+ "smsSendDelay": True, "payFunctionList": [], "minSendTime": "2025-04-21 10:15:32",
137
+ "completedCount": 4, "skippedCount": 0, "openRate": 1, "clickRate": 0, "orderIncome": 0,
138
+ "openDistinctUserRate": 1, "clickDistinctUserRate": 0}, "completedCount": 4,
139
+ "skippedCount": 0, "openRate": 1, "clickRate": 0, "orderIncome": 0, "openDistinctUserRate": 1,
140
+ "clickDistinctUserRate": 0}, "id": "2503b475-ce3e-4906-ab04-0ebc387f0d7e"}],
141
+ "showDataStartTime": 1745164800000, "showDataEndTime": 1745251199000}
142
+ # mock_pulsar = MockFlow.check_flow(mock_domain=_url, host_domain=host_domain, cookies=cookies,
143
+ # flow_id="FLOW6941975456855532553", pulsar=params,
144
+ # update_flow_params=update_flow_params)
145
+ # print(mock_pulsar)
146
+
147
+ # mock_pulsar_step1, _ = MockFlow.check_flow(mock_domain=_url, host_domain=host_domain, cookies=cookies,
148
+ # flow_id="FLOW6941975456855532553", pulsar=params,
149
+ # update_flow_params=update_flow_params, split_steps="one")
150
+ # mock_pulsar_step2 = MockFlow.check_flow(mock_domain=_url, host_domain=host_domain, cookies=cookies,
151
+ # flow_id="FLOW6941975456855532553", old_flow_counts=mock_pulsar_step1,
152
+ # print(mock_pulsar_step1)
153
+ # print(mock_pulsar_step2)
154
+
155
+ # split_steps="two")
156
+ # # node_counts, versions = MockFlow.get_current_flow(host_domain=host_domain, cookies=cookies,
97
157
  # flow_id="FLOW6749144046546626518")
98
- print(mock_pulsar)
158
+
159
+ # 调试
160
+ # # 示例字典
161
+ # my_dict = {'name': 'Alice', 'age': 25, 'city': 'New York'}
162
+ # # 提取所有键到列表
163
+ # key_list = list(my_dict)
164
+ # print(key_list)
165
+ a = ["1", "3", "5"]
166
+ # b = ["3", "1", "5"]
167
+ # if a.sort() == b.sort():
168
+ # print(1)
169
+ # else:
170
+ # print(2)
171
+
172
+ # 断言邮件
173
+ loginEmail, password = 'lulu9600000@gmail.com', 'evvurakhttndwspx'
174
+ email_property = [{'1AutoTest-固定B-营销-生产2.0-2025-04-24 10:19:47.341333-🔥🔥': {'activityId': 408764,
175
+ 'utmConfigInfo': {
176
+ 'utmSource': '1',
177
+ 'utmMedium': '2',
178
+ 'utmCampaign': '3'},
179
+ 'receiveAddress': 'autotest-smartpushpro5@smartpush.com',
180
+ 'sender': 'SmartPush_Pro5_ec2自动化店铺 AutoTestName',
181
+ 'subtitle': 'AutoTest-2025-04-24 10:19:47.341333-subtitle-[[contact.name]]-🔥🔥'}},
182
+ {'AutoTest-固定B-营销-生产2.0-2025-04-24 10:19:59.023150-🔥🔥': {'activityId': 408765,
183
+ 'utmConfigInfo': {'utmSource': '1',
184
+ 'utmMedium': '2',
185
+ 'utmCampaign': '3'},
186
+ 'receiveAddress': '1autotest-smartpushpro5@smartpush.com',
187
+ 'sender': 'SmartPush_Pro5_ec2自动化店铺 AutoTestName',
188
+ 'subtitle': 'AutoTest-2025-04-24 10:19:59.023150-subtitle-[[contact.name]]-🔥🔥'}},
189
+ {'测试邮件-AutoTest_营销_生产2.0_2025_04_24 10:20:28.529290_🔥🔥-😈': {'activityId': None,
190
+ 'utmConfigInfo': None,
191
+ 'receiveAddress': 'autotest-smartpushpro5@smartpush.com',
192
+ 'sender': '1SmartPush_Pro5_ec2自动化店铺 AutoTestName',
193
+ 'subtitle': '营销测试邮件-2025-04-24 10:20:29.560357-😈'}}]
194
+ result = EmailUtlis.check_email_content(emailProperty=email_property, loginEmail=loginEmail, password=password)
195
+ print(result)
196
+
197
+ ccc = {
198
+ "id": "FLOW6966717528141252274",
199
+ "version": "2",
200
+ "triggerId": "c1001",
201
+ "templateId": "",
202
+ "showData": False,
203
+ "flowChange": True,
204
+ "nodes": [
205
+ {
206
+ "type": "trigger",
207
+ "data": {
208
+ "trigger": {
209
+ "trigger": "c1001",
210
+ "group": "",
211
+ "suggestionGroupId": "",
212
+ "triggerStock": False,
213
+ "completedCount": 1,
214
+ "skippedCount": 0
215
+ },
216
+ "completedCount": 1,
217
+ "skippedCount": 0
218
+ },
219
+ "id": "049fd321-5a22-4f92-9692-a3da9507ee4b"
220
+ },
221
+ {
222
+ "type": "delay",
223
+ "data": {
224
+ "delay": {
225
+ "type": "relative",
226
+ "relativeTime": 0,
227
+ "relativeUnit": "MINUTES",
228
+ "designatedTime": ""
229
+ },
230
+ "completedCount": 1
231
+ },
232
+ "id": "09ff19db-33a3-41d8-88e9-12e6017ddfd3"
233
+ },
234
+ {
235
+ "type": "sendLetter",
236
+ "data": {
237
+ "sendLetter": {
238
+ "id": 373090,
239
+ "activityTemplateId": 373090,
240
+ "activityName": "flowActivity_0aGnZ9",
241
+ "activityImage": "http://cdn.smartpushedm.com/frontend/smart-push/staging/1644395920444/1745576879501/1745576881592_c412cc2e.jpeg",
242
+ "emailName": "邮件发送",
243
+ "merchantId": "1644395920444",
244
+ "merchantName": "SmartPush4_ec2_自动化店铺",
245
+ "brandName": "SmartPush4_ec2_自动化店铺 AutoTestName",
246
+ "currency": "JP¥",
247
+ "activityType": "NORMAL",
248
+ "activityStatus": "ACTIVE",
249
+ "createTime": 1745576857268,
250
+ "updateTime": 1745576973175,
251
+ "createDate": "2025-04-25 18:27:37",
252
+ "updateDate": "2025-04-25 18:29:33",
253
+ "pickContactPacks": [],
254
+ "excludeContactPacks": [],
255
+ "customerGroupIds": [],
256
+ "excludeCustomerGroupIds": [],
257
+ "schemaAnalysis": "{\"schema\":{\"Stage\":[\"a4a9fba2a\"],\"Header\":[\"84ba788da\"],\"Column\":[\"98d909a48\",\"8cab9aa48\",\"b3bcabad7\"],\"TextSet\":[\"8298cb99a\"],\"Section\":[\"84ba7bbda\"],\"Logo\":[\"b98abb998\",\"8a9b4bafa\"],\"Footer\":[\"b8bbabad9\"],\"Subscribe\":[\"b39b6a94a\"]}}",
258
+ "pickContactInfos": [],
259
+ "excludeContactInfos": [],
260
+ "customerGroupInfos": [],
261
+ "excludeCustomerGroupInfos": [],
262
+ "sender": "SmartPush4_ec2_自动化店铺 AutoTestName",
263
+ "senderDomain": "DEFAULT_DOMAIN",
264
+ "domainType": 3,
265
+ "receiveAddress": "autotest-smartpush4@smartpush.com",
266
+ "originTemplate": 887,
267
+ "collectTemplate": 0,
268
+ "currentJsonSchema": "{\"id\":\"a4a9fba2a\",\"type\":\"Stage\",\"props\":{\"backgroundColor\":\"#EAEDF1\",\"width\":\"600px\",\"fullWidth\":\"normal-width\"},\"children\":[{\"id\":\"84ba788da\",\"type\":\"Header\",\"props\":{\"backgroundColor\":\"#ffffff\",\"borderLeft\":\"1px none #ffffff\",\"borderRight\":\"1px none #ffffff\",\"borderTop\":\"1px none #ffffff\",\"borderBottom\":\"1px none #ffffff\",\"paddingTop\":\"0px\",\"paddingBottom\":\"0px\",\"paddingLeft\":\"0px\",\"paddingRight\":\"0px\",\"cols\":[12]},\"children\":[{\"id\":\"98d909a48\",\"type\":\"Column\",\"props\":{},\"children\":[{\"id\":\"8298cb99a\",\"type\":\"TextSet\",\"props\":{\"list\":[{\"borderWidth\":\"1px\",\"borderStyle\":\"none\",\"content\":\"<p style=\\\"line-height: 3; text-align: right;\\\"><span style=\\\"color: #000000; font-size: 12px; font-family: arial, sans-serif;\\\"><a style=\\\"color: #000000;\\\" href=\\\"${viewInWebApiUrl}\\\">Can't see the email? Please <span style=\\\"color: #3598db;\\\">click here</span></a></span></p>\",\"paddingLeft\":\"10px\",\"paddingRight\":\"10px\",\"paddingTop\":\"0px\",\"paddingBottom\":\"0px\",\"borderColor\":\"#ffffff\"}],\"containerBackgroundColor\":\"transparent\",\"paddingLeft\":\"10px\",\"paddingRight\":\"10px\",\"paddingTop\":\"10px\",\"paddingBottom\":\"10px\"},\"children\":[]}]}]},{\"id\":\"84ba7bbda\",\"type\":\"Section\",\"props\":{\"backgroundColor\":\"#ffffff\",\"borderLeft\":\"1px none #ffffff\",\"borderRight\":\"1px none #ffffff\",\"borderTop\":\"1px none #ffffff\",\"borderBottom\":\"1px none #ffffff\",\"paddingTop\":\"0px\",\"paddingBottom\":\"0px\",\"paddingLeft\":\"0px\",\"paddingRight\":\"0px\",\"cols\":[12]},\"children\":[{\"id\":\"8cab9aa48\",\"type\":\"Column\",\"props\":{},\"children\":[{\"id\":\"b98abb998\",\"type\":\"Logo\",\"props\":{\"width\":120,\"height\":120,\"imgRatio\":1,\"src\":\"https://cdn.smartpushedm.com/frontend/smart-push/staging/1644395920444/1705904366610_253772e1.png?width=120&height=120\",\"href\":\"https://smartpush4.myshoplinestg.com\",\"align\":\"center\",\"containerBackgroundColor\":\"transparent\",\"paddingLeft\":\"20px\",\"paddingRight\":\"20px\",\"paddingTop\":\"20px\",\"paddingBottom\":\"20px\",\"paddingCondition\":true,\"segmentTypeConfig\":1},\"children\":[]},{\"id\":\"8a9b4bafa\",\"type\":\"Logo\",\"props\":{\"width\":120,\"height\":120,\"imgRatio\":1,\"src\":\"https://cdn.smartpushedm.com/frontend/smart-push/staging/1644395920444/1705904366610_253772e1.png?width=120&height=120\",\"href\":\"https://smartpush4.myshoplinestg.com\",\"align\":\"center\",\"containerBackgroundColor\":\"transparent\",\"paddingLeft\":\"20px\",\"paddingRight\":\"20px\",\"paddingTop\":\"20px\",\"paddingBottom\":\"20px\",\"paddingCondition\":true,\"segmentTypeConfig\":1},\"children\":[]}]}]},{\"id\":\"b8bbabad9\",\"type\":\"Footer\",\"props\":{\"backgroundColor\":\"#ffffff\",\"borderLeft\":\"1px none #ffffff\",\"borderRight\":\"1px none #ffffff\",\"borderTop\":\"1px none #ffffff\",\"borderBottom\":\"1px none #ffffff\",\"paddingTop\":\"0px\",\"paddingBottom\":\"0px\",\"paddingLeft\":\"0px\",\"paddingRight\":\"0px\",\"cols\":[12]},\"children\":[{\"id\":\"b3bcabad7\",\"type\":\"Column\",\"props\":{},\"children\":[{\"id\":\"b39b6a94a\",\"type\":\"Subscribe\",\"props\":{\"content\":\"<div class='sp-font-12'><p style=\\\"text-align: center; \\\" data-mce-style=\\\"text-align: center; \\\"><em><span class='sp-font-12' style=\\\"font-size: 12px; color: rgb(122, 132, 153);\\\" data-mce-style=\\\"font-size: 12px; color: #7a8499;\\\">Please add us to your email contacts list to receive exclusive recommendations!</span></em></p><p style=\\\"text-align: center; \\\" data-mce-style=\\\"text-align: center; \\\"><em><span class='sp-font-12' style=\\\"font-size: 12px; color: rgb(122, 132, 153);\\\" data-mce-style=\\\"font-size: 12px; color: #7a8499;\\\">You are receiving this message from [[shopName]] because you have signed up for subscriptions to receive information about products, services, and campaigns.</span></em></p></div><div class=\\\"sp-font-12\\\" style=\\\"color: rgb(122, 132, 153); font-family: arial, helvetica, sans-serif, Arial, Helvetica, sans-serif; font-size: 12px; text-align: center; margin-top: 12px;padding-left: 10px; padding-right: 10px; padding-bottom: 20px;\\\"><div>Questions? Please <span style=color:#479EEF;text-decoration:underline>contact us</span>, we are glad to help.</div><div>If you don't want to receive our message, just <span style=color:#479EEF;text-decoration:underline>click here</span> to cancel the subscription.</div></div><div class=\\\"sp-font-12\\\" style=\\\"color: rgb(122, 132, 153); font-size: 12px; text-align: center; font-style: oblique;\\\">Questions? Please <a href=[[customerEmail]] style=\\\"color:#479EEF;text-decoration:underline\\\" rel=\\\"noreferrer\\\">contact us</a>, we are glad to help.</div><div class=\\\"sp-font-12\\\" style=\\\"color: rgb(122, 132, 153); font-size: 12px; text-align: center; font-style: oblique;\\\">If you don't want to receive our message, just <a href=[[unsubscribe.url]] target=\\\"_blank\\\" style=\\\"color:#479EEF;text-decoration:underline\\\" rel=\\\"noreferrer\\\">click here</a> to cancel the subscription.</div>\",\"containerBackgroundColor\":\"transparent\"},\"children\":[]}]}]}],\"extend\":{\"version\":\"1.0.0\",\"updateTime\":\"2025-04-25T10:27:59.497Z\"}}",
269
+ "currentHtml": "<!doctype html>\n<html xmlns=\"http://www.w3.org/1999/xhtml\" xmlns:v=\"urn:schemas-microsoft-com:vml\" xmlns:o=\"urn:schemas-microsoft-com:office:office\">\n <head>\n <title></title>\n <!--[if !mso]><!-->\n <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n <!--<![endif]-->\n <meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n <style type=\"text/css\">\n #outlook a { padding:0; }\n body { margin:0;padding:0;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%; }\n table, td { border-collapse:collapse;mso-table-lspace:0pt;mso-table-rspace:0pt; }\n img { border:0;line-height:100%; outline:none;text-decoration:none;-ms-interpolation-mode:bicubic; }\n pre{margin: 0;}p{ display: block;margin:0;}\n </style>\n <!--[if mso]>\n <noscript>\n <xml>\n <o:OfficeDocumentSettings>\n <o:AllowPNG/>\n <o:PixelsPerInch>96</o:PixelsPerInch>\n </o:OfficeDocumentSettings>\n </xml>\n </noscript>\n <![endif]-->\n <!--[if lte mso 11]>\n <style type=\"text/css\">\n .mj-outlook-group-fix { width:100% !important; }\n </style>\n <![endif]-->\n \n <!--[if !mso]><!-->\n <link href=\"https://fonts.googleapis.com/css?family=Ubuntu:300,400,500,700\" rel=\"stylesheet\" type=\"text/css\">\n <style type=\"text/css\">\n @import url(https://fonts.googleapis.com/css?family=Ubuntu:300,400,500,700);\n </style>\n <!--<![endif]-->\n\n \n \n <style type=\"text/css\">\n @media only screen and (min-width:480px) {\n .mj-column-per-100 { width:100% !important; max-width: 100%; }\n }\n </style>\n <style media=\"screen and (min-width:480px)\">\n .moz-text-html .mj-column-per-100 { width:100% !important; max-width: 100%; }\n </style>\n \n \n <style type=\"text/css\">\n \n \n </style>\n <style type=\"text/css\">\n @import url(https://fonts.googleapis.com/css?family=Arvo:400|Bodoni+Moda:400|DM+Sans:400|Poppins:400|Hammersmith+One:400|Libre+Baskerville:400|Lexend+Giga:400|Ubuntu:400|Montserrat:400|Nunito:400|News+Cycle:400|Roboto:400|Oswald:400);@import url(https://fonts.googleapis.com/css?family=Asar:400|Bruno+Ace:400|Cantata+One:400|League+Gothic:400|Long+Cang:400|Lovers+Quarrel:400|Nanum+Gothic+Coding:400|Nanum+Myeongjo:400|Noto+Sans+Kaithi:400|Noto+Sans+Kannada:400|Noto+Sans+Math:400|Noto+Sans+Syloti+Nagri:400|Noto+Serif+JP:400|Playwrite+AT+Guides:400|Saira+Extra+Condensed:400|Tsukimi+Rounded:400|Waiting+for+the+Sunrise:400);h1,\nh2,\nh3,\nh4,\nh5 {\n font-weight: bold;\n margin-bottom: 0;\n}\np {\n margin-top: 0;\n margin-bottom: 0;\n min-height: 1em;\n}\n\nul {\n margin-bottom: 0;\n}\n\nth {\n font-weight: bold;\n}\n\na {\n text-decoration: none;\n}\n\na::-webkit-scrollbar {\n -webkit-appearance: none;\n}\n\na::-webkit-scrollbar:horizontal {\n max-height: 8px;\n}\n\na::-webkit-scrollbar-thumb {\n border-radius: 8px;\n background-color: rgba(0, 0, 0, 0.5);\n}\n\nul,\nol,\ndl {\n margin-top: 16px !important;\n}\n\npre {\n word-break: break-word;\n padding: 0;\n margin: 0;\n white-space: inherit !important;\n}\n\npre p {\n word-break: break-word;\n padding: 0;\n margin: 0;\n color: #000000;\n}\n\nspan[style*='color'] a {\n color: inherit;\n}\n\n.mj-column-no-meida-100{\n width: 100% !important;\n}\n.mj-column-no-meida-50{\n width: 50% !important;\n}\n.mj-column-no-meida-33-333333333333336{\n width: 33.333333333333336% !important;\n}\n.mj-column-no-meida-25{\n width: 25% !important;\n}\n\n.white-nowrap {\n white-space: nowrap !important;\n}\n\n/* 间距 */\n.sp-m-p-0 {\n margin: 0;\n padding: 0;\n}\n\n.nps-content-span a {\n color: inherit !important;\n}.sp-font-12 {\n font-size: 12px !important;\n}\n\n.sp-font-14 {\n font-size: 14px !important;\n}\n\n.sp-font-16 {\n font-size: 16px !important;\n}\n\n.sp-font-18 {\n font-size: 18px !important;\n}\n\n.sp-font-20 {\n font-size: 20px !important;\n}\n\n.sp-font-22 {\n font-size: 22px !important;\n}\n\n.sp-font-24 {\n font-size: 24px !important;\n}\n\n.sp-font-26 {\n font-size: 26px !important;\n}\n\n.sp-font-28 {\n font-size: 28px !important;\n}\n\n.sp-font-30 {\n font-size: 30px !important;\n}\n\n.sp-font-32 {\n font-size: 32px !important;\n}\n\n.sp-font-34 {\n font-size: 34px !important;\n}\n\n.sp-font-36 {\n font-size: 36px !important;\n}\n\n.sp-font-38 {\n font-size: 38px !important;\n}\n\n.sp-font-40 {\n font-size: 40px !important;\n}\n\n.sp-font-42 {\n font-size: 42px !important;\n}\n\n.sp-font-44 {\n font-size: 44px !important;\n}\n\n.sp-font-46 {\n font-size: 46px !important;\n}\n\n.sp-font-48 {\n font-size: 48px !important;\n}\n\n.sp-font-50 {\n font-size: 50px !important;\n}\n\n.sp-font-52 {\n font-size: 52px !important;\n}\n\n.sp-font-54 {\n font-size: 54px !important;\n}\n\n.sp-font-56 {\n font-size: 56px !important;\n}\n\n.sp-font-58 {\n font-size: 58px !important;\n}\n\n.sp-font-60 {\n font-size: 60px !important;\n}\n\n.sp-image-icon {\n width: 50px;\n}\n\n@media only screen and (max-width:600px) {\n\n .sp-font-12 {\n font-size: 12px !important;\n }\n\n .sp-font-14 {\n font-size: 12px !important;\n }\n\n .sp-font-16 {\n font-size: 12px !important;\n }\n\n .sp-font-18 {\n font-size: 13px !important;\n }\n\n .sp-font-20 {\n font-size: 15px !important;\n }\n\n .sp-font-22 {\n font-size: 16px !important;\n }\n\n .sp-font-24 {\n font-size: 18px !important;\n }\n\n .sp-font-26 {\n font-size: 19px !important;\n }\n\n .sp-font-28 {\n font-size: 21px !important;\n }\n\n .sp-font-30 {\n font-size: 22px !important;\n }\n\n .sp-font-32 {\n font-size: 24px !important;\n }\n\n .sp-font-34 {\n font-size: 25px !important;\n }\n\n .sp-font-36 {\n font-size: 27px !important;\n }\n\n .sp-font-38 {\n font-size: 28px !important;\n }\n\n .sp-font-40 {\n font-size: 30px !important;\n }\n\n .sp-font-42 {\n font-size: 31px !important;\n }\n\n .sp-font-44 {\n font-size: 32px !important;\n }\n\n .sp-font-46 {\n font-size: 33px !important;\n }\n\n .sp-font-48 {\n font-size: 34px !important;\n }\n\n .sp-font-50 {\n font-size: 35px !important;\n }\n\n .sp-font-52 {\n font-size: 36px !important;\n }\n\n .sp-font-54 {\n font-size: 37px !important;\n }\n\n .sp-font-56 {\n font-size: 38px !important;\n }\n\n .sp-font-58 {\n font-size: 39px !important;\n }\n\n .sp-font-60 {\n font-size: 40px !important;\n }\n\n .sp-image-icon {\n width: 28px !important;\n }\n\n}@media only screen and (max-width:480px) {\n\n .sp-img-h-1-TwoVertical-11,\n .sp-img-h-1-TwoHorizontalColumns-11 {\n height: 170px !important;\n }\n\n .sp-img-h-1-TwoVertical-23,\n .sp-img-h-1-TwoHorizontalColumns-23 {\n height: 243px !important;\n }\n\n .sp-img-h-1-TwoVertical-34,\n .sp-img-h-1-TwoHorizontalColumns-34 {\n height: 227px !important;\n }\n\n .sp-img-h-1-TwoVertical-43,\n .sp-img-h-1-TwoHorizontalColumns-43 {\n height: 127px !important;\n }\n\n .sp-img-h-1-ThreeHorizontalColumns-11 {\n height: 109px !important;\n }\n\n .sp-img-h-1-ThreeHorizontalColumns-23 {\n height: 163px !important;\n }\n\n .sp-img-h-1-ThreeHorizontalColumns-34 {\n height: 145px !important;\n }\n\n .sp-img-h-1-ThreeHorizontalColumns-43 {\n height: 81px !important;\n }\n\n .sp-img-h-2-TwoVertical-11 {\n height: 164px !important;\n }\n\n .sp-img-h-2-TwoVertical-23 {\n height: 246px !important;\n }\n\n .sp-img-h-2-TwoVertical-34 {\n height: 218px !important;\n }\n\n .sp-img-h-2-TwoVertical-43 {\n height: 123px !important;\n }\n\n .sp-img-h-2-ThreeHorizontalColumns-11,\n .sp-img-h-2-TwoHorizontalColumns-11 {\n height: 76px !important;\n }\n\n .sp-img-h-2-ThreeHorizontalColumns-23,\n .sp-img-h-2-TwoHorizontalColumns-23 {\n height: 113px !important;\n }\n\n .sp-img-h-2-ThreeHorizontalColumns-34,\n .sp-img-h-2-TwoHorizontalColumns-34 {\n height: 101px !important;\n }\n\n .sp-img-h-2-ThreeHorizontalColumns-43,\n .sp-img-h-2-TwoHorizontalColumns-43 {\n height: 57px !important;\n }\n}@media only screen and (min-width: 320px) and (max-width: 599px) {\n .mj-w-50 {\n width: 50% !important;\n max-width: 50%;\n }\n}\n\n@media only screen and (max-width: 480px) {\n .shop-white-mobile {\n width: 100% !important;\n }\n .mj-td-force-100{\n display: inline-block;\n width: 100% !important;\n }\n\n .mj-ImageText-screen {\n width: 100% !important;\n }\n .mj-ImageText-img {\n margin: 0 auto;\n }\n\n .mj-ImageText-margin {\n margin: 0 !important;\n }\n\n .mj-ImageText-margin-zero {\n margin: 0 5px 0 0 !important;\n }\n\n .mj-ImageText-margin-one {\n margin: 0 0 0 5px !important;\n }\n .mj-column-per-50-force {\n width: 50% !important;\n max-width: 50%;\n }\n}\n\n@media only screen and (min-width: 480px) {\n .mj-imagetext-force-100{\n display: inline-block;\n width: 100% !important;\n }\n .mj-column-per-100 {\n width: 100% !important;\n max-width: 100%;\n }\n\n .mj-column-per-50 {\n width: 50% !important;\n max-width: 50%;\n }\n\n .mj-column-per-33-333333333333336 {\n width: 33.333333333333336% !important;\n max-width: 33.333333333333336%;\n }\n\n .mj-column-per-25 {\n width: 25% !important;\n max-width: 25%;\n }\n\n\n .mg-column-per-46-5 {\n width: 46.5% !important;\n max-width: 46.5%;\n }\n\n .mj-AbandonProduct-cloum-align-center {\n align-items: flex-start !important;\n }\n\n\n .mj-OrderInformation-padding-top-220 {\n padding-top: 20px !important;\n }\n\n .mj-OrderInformation-float-left {\n float: left !important;\n }\n}@media only screen and (max-width: 480px) {\n .mt-1{\n margin-top: 1px;\n }\n .mt-2{\n margin-top: 2px;\n }\n .mt-3{\n margin-top: 3px;\n }\n .mt-4{\n margin-top: 4px;\n }\n .mt-5{\n margin-top: 5px;\n }\n .mt-6{\n margin-top: 7px;\n }\n .mt-8{\n margin-top: 9px;\n }\n .mt-10{\n margin-top: 10px;\n }\n\n}\n </style>\n \n </head>\n <body style=\"word-spacing:normal;background-color:#EAEDF1;\">\n \n \n <div\n style=\"background-color:#EAEDF1;\"\n >\n <table className=\"pv-stage\">\n <tbody>\n <tr>\n <td style=\"display:table-column;\"><div style=\"width:1px; height:1px;\"><img style=\"width:1px; height:1px;\" width=\"1\" src=\"${SP_OPEN_EMAIL_URL}\" />\n </div></td>\n </tr>\n </tbody>\n </table><div mso-hide: all; position: fixed; height: 0; max-height: 0; overflow: hidden; font-size: 0; style=\"display:none;\">${emailSubtitle}</div>\n \n <!--[if mso | IE]><table align=\"center\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\" class=\"\" role=\"presentation\" style=\"width:600px;\" width=\"600\" bgcolor=\"#ffffff\" ><tr><td style=\"line-height:0px;font-size:0px;mso-line-height-rule:exactly;\"><![endif]-->\n \n \n <div style=\"background:#ffffff;background-color:#ffffff;margin:0px auto;max-width:600px;\">\n \n <table\n align=\"center\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\" role=\"presentation\" style=\"background:#ffffff;background-color:#ffffff;width:100%;\"\n >\n <tbody>\n <tr>\n <td\n style=\"border-bottom:1px none #ffffff;border-left:1px none #ffffff;border-right:1px none #ffffff;border-top:1px none #ffffff;direction:ltr;font-size:0px;padding:20px 0;padding-bottom:0px;padding-left:0px;padding-right:0px;padding-top:0px;text-align:center;\"\n >\n <!--[if mso | IE]><table role=\"presentation\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\"><tr><td class=\"\" style=\"vertical-align:top;width:598px;\" ><![endif]-->\n \n <div\n class=\"mj-column-per-100 mj-outlook-group-fix\" style=\"font-size:0px;text-align:left;direction:ltr;display:inline-block;vertical-align:top;width:100%;\"\n >\n \n <table\n border=\"0\" cellpadding=\"0\" cellspacing=\"0\" role=\"presentation\" style=\"vertical-align:top;\" width=\"100%\"\n >\n <tbody>\n \n <tr>\n <td\n align=\"left\" style=\"font-size:0px;padding:10px 25px;padding-top:10px;padding-right:10px;padding-bottom:10px;padding-left:10px;word-break:break-word;\"\n >\n \n <table\n cellpadding=\"0\" cellspacing=\"0\" width=\"100%\" border=\"0\" style=\"color:#000000;font-family:Ubuntu, Helvetica, Arial, sans-serif;font-size:13px;line-height:1.5;table-layout:fixed;width:100%;border:none;\"\n >\n <tr style=\"background-color:transparent;\"><td style=\"vertical-align:top;\" valign=\"top\"><table style=\"border-collapse: collapse;width:100%; table-layout: fixed;\"><tbody ><tr><td class=\"sp-font-16\" style=\"text-align:left;background-color:transparent;padding-left:10px;padding-right:10px;padding-top:0px;padding-bottom:0px;font-size:16px;border-style:none;border-color:#ffffff;border-width:1px;\"><pre class=\"mq_AS\" style=\"white-space: inherit;word-break: break-word;\"><p style=\"line-height: 3; text-align: right;\"><span style=\"color: #000000; font-size: 12px; font-family: arial, sans-serif;\"><a style=\"color: #000000;\" href=\"${viewInWebApiUrl}\">Can't see the email? Please <span style=\"color: #3598db;\">click here</span></a></span></p></pre></td></tr></tbody></table></td></tr>\n </table>\n \n </td>\n </tr>\n \n </tbody>\n </table>\n \n </div>\n \n <!--[if mso | IE]></td></tr></table><![endif]-->\n </td>\n </tr>\n </tbody>\n </table>\n \n </div>\n \n \n <!--[if mso | IE]></td></tr></table><table align=\"center\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\" class=\"\" role=\"presentation\" style=\"width:600px;\" width=\"600\" bgcolor=\"#ffffff\" ><tr><td style=\"line-height:0px;font-size:0px;mso-line-height-rule:exactly;\"><![endif]-->\n \n \n <div style=\"background:#ffffff;background-color:#ffffff;margin:0px auto;max-width:600px;\">\n \n <table\n align=\"center\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\" role=\"presentation\" style=\"background:#ffffff;background-color:#ffffff;width:100%;\"\n >\n <tbody>\n <tr>\n <td\n style=\"border-bottom:1px none #ffffff;border-left:1px none #ffffff;border-right:1px none #ffffff;border-top:1px none #ffffff;direction:ltr;font-size:0px;padding:20px 0;padding-bottom:0px;padding-left:0px;padding-right:0px;padding-top:0px;text-align:center;\"\n >\n <!--[if mso | IE]><table role=\"presentation\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\"><tr><td class=\"\" style=\"vertical-align:top;width:598px;\" ><![endif]-->\n \n <div\n class=\"mj-column-per-100 mj-outlook-group-fix\" style=\"font-size:0px;text-align:left;direction:ltr;display:inline-block;vertical-align:top;width:100%;\"\n >\n \n <table\n border=\"0\" cellpadding=\"0\" cellspacing=\"0\" role=\"presentation\" style=\"vertical-align:top;\" width=\"100%\"\n >\n <tbody>\n \n <tr>\n <td\n align=\"left\" style=\"background:transparent;font-size:0px;padding:0;word-break:break-word;\"\n >\n \n <table\n cellpadding=\"0\" cellspacing=\"0\" width=\"100%\" border=\"0\" style=\"color:#000000;font-family:Ubuntu, Helvetica, Arial, sans-serif;font-size:13px;line-height:22px;table-layout:auto;width:100%;border:0;\"\n >\n <tr>\n <td align=\"center\">\n <table style=\"padding:0;margin:0;clear:both;\">\n <tbody style=\"padding:0;margin:0;clear:both;\">\n <tr style=\"padding:0;margin:0;clear:both;\">\n <td style=\"padding:0;margin:0;clear:both;width:120;padding-bottom:20px;padding-left:20px;padding-right:20px;padding-top:20px;\">\n <a href=\"https://smartpush4.myshoplinestg.com\" style=\"padding:0;margin:0;clear:both;\"><img src=\"https://cdn.smartpushedm.com/frontend/smart-push/staging/1644395920444/1705904366610_253772e1.png?width=120&height=120\" style=\"width:120px;max-width:100%;display:block;outline:none;text-decoration:none;height:auto;font-size:0px;object-fit:cover;\" width=\"120\" /></a>\n </td>\n </tr>\n </tbody>\n </table>\n </td>\n </tr>\n </table>\n \n </td>\n </tr>\n \n <tr>\n <td\n align=\"left\" style=\"background:transparent;font-size:0px;padding:0;word-break:break-word;\"\n >\n \n <table\n cellpadding=\"0\" cellspacing=\"0\" width=\"100%\" border=\"0\" style=\"color:#000000;font-family:Ubuntu, Helvetica, Arial, sans-serif;font-size:13px;line-height:22px;table-layout:auto;width:100%;border:0;\"\n >\n <tr>\n <td align=\"center\">\n <table style=\"padding:0;margin:0;clear:both;\">\n <tbody style=\"padding:0;margin:0;clear:both;\">\n <tr style=\"padding:0;margin:0;clear:both;\">\n <td style=\"padding:0;margin:0;clear:both;width:120;padding-bottom:20px;padding-left:20px;padding-right:20px;padding-top:20px;\">\n <a href=\"https://smartpush4.myshoplinestg.com\" style=\"padding:0;margin:0;clear:both;\"><img src=\"https://cdn.smartpushedm.com/frontend/smart-push/staging/1644395920444/1705904366610_253772e1.png?width=120&height=120\" style=\"width:120px;max-width:100%;display:block;outline:none;text-decoration:none;height:auto;font-size:0px;object-fit:cover;\" width=\"120\" /></a>\n </td>\n </tr>\n </tbody>\n </table>\n </td>\n </tr>\n </table>\n \n </td>\n </tr>\n \n </tbody>\n </table>\n \n </div>\n \n <!--[if mso | IE]></td></tr></table><![endif]-->\n </td>\n </tr>\n </tbody>\n </table>\n \n </div>\n \n \n <!--[if mso | IE]></td></tr></table><table align=\"center\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\" class=\"\" role=\"presentation\" style=\"width:600px;\" width=\"600\" bgcolor=\"#ffffff\" ><tr><td style=\"line-height:0px;font-size:0px;mso-line-height-rule:exactly;\"><![endif]-->\n \n \n <div style=\"background:#ffffff;background-color:#ffffff;margin:0px auto;max-width:600px;\">\n \n <table\n align=\"center\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\" role=\"presentation\" style=\"background:#ffffff;background-color:#ffffff;width:100%;\"\n >\n <tbody>\n <tr>\n <td\n style=\"border-bottom:1px none #ffffff;border-left:1px none #ffffff;border-right:1px none #ffffff;border-top:1px none #ffffff;direction:ltr;font-size:0px;padding:20px 0;padding-bottom:0px;padding-left:0px;padding-right:0px;padding-top:0px;text-align:center;\"\n >\n <!--[if mso | IE]><table role=\"presentation\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\"><tr><td class=\"\" style=\"vertical-align:top;width:598px;\" ><![endif]-->\n \n <div\n class=\"mj-column-per-100 mj-outlook-group-fix\" style=\"font-size:0px;text-align:left;direction:ltr;display:inline-block;vertical-align:top;width:100%;\"\n >\n \n <table\n border=\"0\" cellpadding=\"0\" cellspacing=\"0\" role=\"presentation\" style=\"vertical-align:top;\" width=\"100%\"\n >\n <tbody>\n \n <tr>\n <td\n align=\"left\" style=\"font-size:0px;padding:0;word-break:break-word;\"\n >\n \n <table\n cellpadding=\"0\" cellspacing=\"0\" width=\"100%\" border=\"0\" style=\"color:#000000;font-family:Ubuntu, Helvetica, Arial, sans-serif;font-size:13px;line-height:22px;table-layout:fixed;width:100%;border:none;\"\n >\n <table style=\"margin:0;padding:0;width:100%;table-layout:fixed\" class=\"\" sp-id=\"subscribe-area-b39b6a94a\"><tbody><tr style=\"width:100%\"><td style=\"margin:0;padding:0;width:100%;text-align:center;padding-top:20px;padding-left:20px;padding-right:20px;padding-bottom:20px;background-color:transparent;font-family:arial,helvetica,sans-serif,Arial, Helvetica, sans-serif\" class=\"Subscribe\"><table cellPadding=\"0\" cellSpacing=\"0\" style=\"width:100%\"><tbody><tr><td align=\"center\" class=\"sp-font-16\" valign=\"middle\" style=\"padding-left:10px;padding-right:10px;padding-top:10px;text-align:left;font-size:16px\"><div><div class='sp-font-12'><p style=\"text-align: center; \" data-mce-style=\"text-align: center; \"><em><span class='sp-font-12' style=\"font-size: 12px; color: rgb(122, 132, 153);\" data-mce-style=\"font-size: 12px; color: #7a8499;\">Please add us to your email contacts list to receive exclusive recommendations!</span></em></p><p style=\"text-align: center; \" data-mce-style=\"text-align: center; \"><em><span class='sp-font-12' style=\"font-size: 12px; color: rgb(122, 132, 153);\" data-mce-style=\"font-size: 12px; color: #7a8499;\">You are receiving this message from [[shopName]] because you have signed up for subscriptions to receive information about products, services, and campaigns.</span></em></p></div><div class=\"sp-font-12\" style=\"color: rgb(122, 132, 153); font-family: arial, helvetica, sans-serif, Arial, Helvetica, sans-serif; font-size: 12px; text-align: center; margin-top: 12px;padding-left: 10px; padding-right: 10px; padding-bottom: 20px;\"><div>Questions? Please <span style=color:#479EEF;text-decoration:underline>contact us</span>, we are glad to help.</div><div>If you don't want to receive our message, just <span style=color:#479EEF;text-decoration:underline>click here</span> to cancel the subscription.</div></div><div class=\"sp-font-12\" style=\"color: rgb(122, 132, 153); font-size: 12px; text-align: center; font-style: oblique;\">Questions? Please <html xmlns=\"http://www.w3.org/1999/xhtml\"><head></head><body><a href=\"mailto:[[customerEmail]]\" style=\"color:#479EEF;text-decoration:underline\" rel=\"noreferrer\">contact us</a></body></html>, we are glad to help.</div><div class=\"sp-font-12\" style=\"color: rgb(122, 132, 153); font-size: 12px; text-align: center; font-style: oblique;\">If you don't want to receive our message, just <html xmlns=\"http://www.w3.org/1999/xhtml\"><head></head><body><a href=\"[[unsubscribe.url]]\" target=\"_blank\" style=\"color:#479EEF;text-decoration:underline\" rel=\"noreferrer\">click here</a></body></html> to cancel the subscription.</div></div></td></tr><tr><td align=\"center\" valign=\"middle\" height=\"20\" style=\"font-size:12px;font-family:arial,helvetica,sans-serif,Arial, Helvetica, sans-serif;padding-left:10px;padding-right:10px;padding-bottom:20px\"></td></tr><div><tr style=\"${hide_logo}\" sp-id=\"subscribe-dom-b39b6a94a\">\n <td class='sp-font-16' style=\"padding-left:20px;padding-right:20px;padding-top:20px;text-align:center;font-size:16px\" >\n <div style=\"border-top: 1px solid #EEF1F6\">\n <img src=\"https://cdn.smartpushedm.com/frontend/smart-push/product/image/1731577171577_83853d55.png\" style=\"padding: 10px;vertical-align: middle;width: 158px;\"alt=\"\" />\n </div>\n <p style=\"color:#343434;font-size:12px\">Providing content services for [[shopName]]</p>\n </td>\n </tr></div></tbody></table></td></tr></tbody></table>\n </table>\n \n </td>\n </tr>\n \n </tbody>\n </table>\n \n </div>\n \n <!--[if mso | IE]></td></tr></table><![endif]-->\n </td>\n </tr>\n </tbody>\n </table>\n \n </div>\n \n \n <!--[if mso | IE]></td></tr></table><![endif]-->\n \n \n </div>\n \n </body>\n</html>\n ",
270
+ "previewJsonSchema": "{\"id\":\"a4a9fba2a\",\"type\":\"Stage\",\"props\":{\"backgroundColor\":\"#EAEDF1\",\"width\":\"600px\",\"fullWidth\":\"normal-width\"},\"children\":[{\"id\":\"84ba788da\",\"type\":\"Header\",\"props\":{\"backgroundColor\":\"#ffffff\",\"borderLeft\":\"1px none #ffffff\",\"borderRight\":\"1px none #ffffff\",\"borderTop\":\"1px none #ffffff\",\"borderBottom\":\"1px none #ffffff\",\"paddingTop\":\"0px\",\"paddingBottom\":\"0px\",\"paddingLeft\":\"0px\",\"paddingRight\":\"0px\",\"cols\":[12]},\"children\":[{\"id\":\"98d909a48\",\"type\":\"Column\",\"props\":{},\"children\":[{\"id\":\"8298cb99a\",\"type\":\"TextSet\",\"props\":{\"list\":[{\"borderWidth\":\"1px\",\"borderStyle\":\"none\",\"content\":\"<p style=\\\"line-height: 3; text-align: right;\\\"><span style=\\\"color: #000000; font-size: 12px; font-family: arial, sans-serif;\\\"><a style=\\\"color: #000000;\\\" href=\\\"${viewInWebApiUrl}\\\">Can't see the email? Please <span style=\\\"color: #3598db;\\\">click here</span></a></span></p>\",\"paddingLeft\":\"10px\",\"paddingRight\":\"10px\",\"paddingTop\":\"0px\",\"paddingBottom\":\"0px\",\"borderColor\":\"#ffffff\"}],\"containerBackgroundColor\":\"transparent\",\"paddingLeft\":\"10px\",\"paddingRight\":\"10px\",\"paddingTop\":\"10px\",\"paddingBottom\":\"10px\"},\"children\":[]}]}]},{\"id\":\"84ba7bbda\",\"type\":\"Section\",\"props\":{\"backgroundColor\":\"#ffffff\",\"borderLeft\":\"1px none #ffffff\",\"borderRight\":\"1px none #ffffff\",\"borderTop\":\"1px none #ffffff\",\"borderBottom\":\"1px none #ffffff\",\"paddingTop\":\"0px\",\"paddingBottom\":\"0px\",\"paddingLeft\":\"0px\",\"paddingRight\":\"0px\",\"cols\":[12]},\"children\":[{\"id\":\"8cab9aa48\",\"type\":\"Column\",\"props\":{},\"children\":[{\"id\":\"b98abb998\",\"type\":\"Logo\",\"props\":{\"width\":120,\"height\":120,\"imgRatio\":1,\"src\":\"https://cdn.smartpushedm.com/frontend/smart-push/staging/1644395920444/1705904366610_253772e1.png?width=120&height=120\",\"href\":\"https://smartpush4.myshoplinestg.com\",\"align\":\"center\",\"containerBackgroundColor\":\"transparent\",\"paddingLeft\":\"20px\",\"paddingRight\":\"20px\",\"paddingTop\":\"20px\",\"paddingBottom\":\"20px\",\"paddingCondition\":true,\"segmentTypeConfig\":1},\"children\":[]},{\"id\":\"8a9b4bafa\",\"type\":\"Logo\",\"props\":{\"width\":120,\"height\":120,\"imgRatio\":1,\"src\":\"https://cdn.smartpushedm.com/frontend/smart-push/staging/1644395920444/1705904366610_253772e1.png?width=120&height=120\",\"href\":\"https://smartpush4.myshoplinestg.com\",\"align\":\"center\",\"containerBackgroundColor\":\"transparent\",\"paddingLeft\":\"20px\",\"paddingRight\":\"20px\",\"paddingTop\":\"20px\",\"paddingBottom\":\"20px\",\"paddingCondition\":true,\"segmentTypeConfig\":1},\"children\":[]}]}]},{\"id\":\"b8bbabad9\",\"type\":\"Footer\",\"props\":{\"backgroundColor\":\"#ffffff\",\"borderLeft\":\"1px none #ffffff\",\"borderRight\":\"1px none #ffffff\",\"borderTop\":\"1px none #ffffff\",\"borderBottom\":\"1px none #ffffff\",\"paddingTop\":\"0px\",\"paddingBottom\":\"0px\",\"paddingLeft\":\"0px\",\"paddingRight\":\"0px\",\"cols\":[12]},\"children\":[{\"id\":\"b3bcabad7\",\"type\":\"Column\",\"props\":{},\"children\":[{\"id\":\"b39b6a94a\",\"type\":\"Subscribe\",\"props\":{\"content\":\"<div class='sp-font-12'><p style=\\\"text-align: center; \\\" data-mce-style=\\\"text-align: center; \\\"><em><span class='sp-font-12' style=\\\"font-size: 12px; color: rgb(122, 132, 153);\\\" data-mce-style=\\\"font-size: 12px; color: #7a8499;\\\">Please add us to your email contacts list to receive exclusive recommendations!</span></em></p><p style=\\\"text-align: center; \\\" data-mce-style=\\\"text-align: center; \\\"><em><span class='sp-font-12' style=\\\"font-size: 12px; color: rgb(122, 132, 153);\\\" data-mce-style=\\\"font-size: 12px; color: #7a8499;\\\">You are receiving this message from [[shopName]] because you have signed up for subscriptions to receive information about products, services, and campaigns.</span></em></p></div><div class=\\\"sp-font-12\\\" style=\\\"color: rgb(122, 132, 153); font-family: arial, helvetica, sans-serif, Arial, Helvetica, sans-serif; font-size: 12px; text-align: center; margin-top: 12px;padding-left: 10px; padding-right: 10px; padding-bottom: 20px;\\\"><div>Questions? Please <span style=color:#479EEF;text-decoration:underline>contact us</span>, we are glad to help.</div><div>If you don't want to receive our message, just <span style=color:#479EEF;text-decoration:underline>click here</span> to cancel the subscription.</div></div><div class=\\\"sp-font-12\\\" style=\\\"color: rgb(122, 132, 153); font-size: 12px; text-align: center; font-style: oblique;\\\">Questions? Please <a href=[[customerEmail]] style=\\\"color:#479EEF;text-decoration:underline\\\" rel=\\\"noreferrer\\\">contact us</a>, we are glad to help.</div><div class=\\\"sp-font-12\\\" style=\\\"color: rgb(122, 132, 153); font-size: 12px; text-align: center; font-style: oblique;\\\">If you don't want to receive our message, just <a href=[[unsubscribe.url]] target=\\\"_blank\\\" style=\\\"color:#479EEF;text-decoration:underline\\\" rel=\\\"noreferrer\\\">click here</a> to cancel the subscription.</div>\",\"containerBackgroundColor\":\"transparent\"},\"children\":[]}]}]}],\"extend\":{\"version\":\"1.0.0\",\"updateTime\":\"2025-04-25T10:27:59.497Z\"}}",
271
+ "generatedHtml": False,
272
+ "templateUrl": "https://cdn2.smartpushedm.com/material_ec2/2024-07-08/c316faf4623d4638893a127e150377f0/v2-545b3673f3db07397babfb71755ecee0_720w.png",
273
+ "sendStrategy": "NOW",
274
+ "totalReceiver": 0,
275
+ "utmConfigEnable": False,
276
+ "subtitle": "",
277
+ "language": "en",
278
+ "languageName": "English",
279
+ "timezone": "Asia/Macao",
280
+ "timezoneGmt": "GMT+08:00",
281
+ "type": "FLOW",
282
+ "relId": "FLOW6966717528141252274",
283
+ "parentId": "0",
284
+ "nodeId": "15630c25-75fa-4456-a6ee-a2bd1e3e64a1",
285
+ "version": "2",
286
+ "nodeOrder": 0,
287
+ "sendType": "EMAIL",
288
+ "productInfos": [],
289
+ "blocks": [
290
+ {
291
+ "domId": "subscribe-dom-b39b6a94a",
292
+ "blockId": "",
293
+ "areaId": "",
294
+ "type": "SP_LOGO",
295
+ "column": 1,
296
+ "fillStyle": 0,
297
+ "ratio": "",
298
+ "currencySymbolShow": 1,
299
+ "thousandthSep": True,
300
+ "decimalPoint": 2
301
+ }
302
+ ],
303
+ "discountCodes": [],
304
+ "reviews": [],
305
+ "awards": [],
306
+ "selectProducts": [],
307
+ "createSource": "BUILD_ACTIVITY",
308
+ "contentChange": True,
309
+ "activityChange": False,
310
+ "imageVersion": "1745576879501",
311
+ "subActivityList": [],
312
+ "warmupPack": 0,
313
+ "boosterEnabled": False,
314
+ "smartSending": True,
315
+ "boosterCreated": False,
316
+ "gmailPromotion": False,
317
+ "sendTimeType": "FIXED",
318
+ "sendTimezone": "B_TIMEZONE",
319
+ "sendTimeDelay": False,
320
+ "sendOption": 1,
321
+ "hasUserBlock": False,
322
+ "hasAutoBlock": False,
323
+ "smsSendDelay": True,
324
+ "payFunctionList": [],
325
+ "minSendTime": "2025-04-25 18:27:37",
326
+ "completedCount": 1,
327
+ "skippedCount": 0,
328
+ "openRate": 1,
329
+ "clickRate": 0,
330
+ "orderIncome": 0,
331
+ "openDistinctUserRate": 1,
332
+ "clickDistinctUserRate": 0
333
+ },
334
+ "completedCount": 1,
335
+ "skippedCount": 0,
336
+ "openRate": 1,
337
+ "clickRate": 0,
338
+ "orderIncome": 0,
339
+ "openDistinctUserRate": 1,
340
+ "clickDistinctUserRate": 0
341
+ },
342
+ "id": "15630c25-75fa-4456-a6ee-a2bd1e3e64a1"
343
+ }
344
+ ],
345
+ "showDataStartTime": None,
346
+ "showDataEndTime": None
347
+ }
348
+ # print(ccc)
@@ -0,0 +1,305 @@
1
+ #!/usr/bin/env python
2
+ # _*_ coding:utf-8 _*_
3
+ import random
4
+ import re
5
+ import ssl
6
+ from datetime import timedelta, datetime
7
+ from urllib.parse import parse_qs
8
+ from retry import retry
9
+ import imapclient
10
+ import pyzmail
11
+ import requests
12
+ from bs4 import BeautifulSoup
13
+ from urllib import parse
14
+
15
+ junkEmail, allEmail = "[Gmail]/垃圾邮件", "[Gmail]/所有邮件"
16
+
17
+
18
+ def forParseEmailContent(UIDs, isReturnHtml=False):
19
+ """
20
+ 解析邮件内容
21
+ @param UIDs:
22
+ @return:
23
+ """
24
+ global _subject, _sender, _from_email, _recipient, _receiveDate, _replay
25
+ messageInfo = {}
26
+ subjectList = []
27
+ if len(UIDs) > 0:
28
+ rawMessages = imapObj.fetch(UIDs, ['BODY[]'])
29
+
30
+ for uid in UIDs:
31
+ message = pyzmail.PyzMessage.factory(rawMessages[uid][b'BODY[]'])
32
+ # 解析邮件内容
33
+ _subject = message.get_subject()
34
+ subjectList.append(_subject)
35
+ _sender = message.get_addresses('from')[0][0]
36
+ _from_email = message.get_addresses('from')[0][1]
37
+ _recipient = message.get_addresses('to')[0][0]
38
+ if message.get_addresses('reply-to'):
39
+ _replay = message.get_addresses('reply-to')[0][0]
40
+ _receiveDate = message.get('date')
41
+ tempData = {"sender": _sender, "from_email": _from_email, "recipient": _recipient,
42
+ "receiveAddress": _replay if _replay else None, "receiveDate": _receiveDate}
43
+ if len(UIDs) == 1:
44
+ messageInfo.update({_subject: tempData})
45
+ else:
46
+ if messageInfo.get(_subject) is None:
47
+ messageInfo.update({_subject: [tempData]})
48
+ else:
49
+ tempList = messageInfo.get(_subject)
50
+ tempList.append(tempData)
51
+ messageInfo.update({_subject: tempList})
52
+ # html内容解析
53
+ if isReturnHtml:
54
+ htmlBody = message.html_part.get_payload().decode(message.html_part.charset)
55
+ # print('邮件html:', htmlBody)
56
+
57
+ if not isReturnHtml:
58
+ # print("------------------")
59
+ # print("邮件主旨:" + _subject)
60
+ # print("发件人:" + _sender)
61
+ # print("发件邮箱:" + _from_email)
62
+ # print("收件人邮箱:" + _recipient)
63
+ # print("回复邮箱:" + _replay)
64
+ # print('接收邮件日期:' + _receiveDate)
65
+ return messageInfo
66
+ else:
67
+ return messageInfo, htmlBody
68
+
69
+
70
+ def selectFolderGetUids(imapObj, foldersName, text=None):
71
+ """
72
+ @param imapObj:邮件对象
73
+ @param foldersName: 文件夹
74
+ @param text: 搜索文本
75
+ @return: Uid,文件的id
76
+ """
77
+ imapObj.select_folder(foldersName, readonly=True)
78
+ # print(f"在 【{foldersName}】 中搜索关键词---> :{text}")
79
+ if text:
80
+ # 通过标题搜索
81
+ UIDs = imapObj.gmail_search(text)
82
+ else:
83
+ # 查找所有
84
+ UIDs = imapObj.gmail_search(u'All')
85
+ return UIDs
86
+
87
+
88
+ def loginShowFoldersEmail(email, password):
89
+ # 登录邮件
90
+ # imaplib._MAXLINE = 10000000 # 最大行数限制
91
+ context = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2)
92
+ imapObj = imapclient.IMAPClient('imap.gmail.com', ssl=True, ssl_context=context)
93
+ imapObj.login(email, password)
94
+ folders = imapObj.list_folders()
95
+ print("所有的邮件文件夹:", [folder[2] for folder in folders])
96
+ return imapObj
97
+
98
+
99
+ def getTodayDateTime():
100
+ # 获取当天日期
101
+ since = datetime.utcnow() - timedelta(minutes=1)
102
+ receiveTime = since.strftime('%d-%b-%Y')
103
+ return receiveTime
104
+
105
+
106
+ def fetchEmail(imapObj, UIDs):
107
+ """
108
+ 标识为已读(打开邮件)
109
+ @param imapObj:
110
+ @param UIDs:
111
+ @return:
112
+ """
113
+ imapObj.fetch(UIDs, ['BODY[]'])
114
+ return True
115
+
116
+
117
+ def assertEmail(emailProperty=None, is_check_email_property=True):
118
+ errors = []
119
+ for temp in emailProperty:
120
+ _subject = list(temp.keys())[0]
121
+ # print("\n----执行遍历断言----> ", _subject)
122
+ try:
123
+ UIDs = selectFolderGetUids(imapObj, allEmail, _subject)
124
+ assert UIDs
125
+ except AssertionError:
126
+ UIDs = selectFolderGetUids(imapObj, junkEmail, _subject)
127
+ try:
128
+ assert UIDs
129
+ except AssertionError:
130
+ errors.append({_subject: "未收到邮件"})
131
+ is_check_email_property = False
132
+ # raise AssertionError(f"找不到相符的邮件内容:{_subject}")
133
+ finally:
134
+ # 断言回复邮箱和发件人
135
+ if is_check_email_property:
136
+ EmailContentAll = forParseEmailContent(UIDs)
137
+ property_result = assertEmailProperty(temp[_subject], EmailContentAll[_subject])
138
+ if len(property_result) > 0:
139
+ errors.append({_subject: property_result})
140
+ return [True, "邮件内容断言成功"] if len(errors) == 0 else [False, {"邮件内容断言失败": errors}]
141
+
142
+
143
+ def assertEmailProperty(emailProperty, ParseEmailContent):
144
+ """
145
+ 断言邮件内容
146
+ @param emailProperty:
147
+ @param ParseEmailContent:assertEmail
148
+ @return:
149
+ """
150
+ property_errors = []
151
+ # print("原始数据", ParseEmailContent)
152
+ if isinstance(ParseEmailContent, list):
153
+ _parseEmailContent = ParseEmailContent[0]
154
+ else:
155
+ # 新增-发件人、回复邮箱断言
156
+ _parseEmailContent = ParseEmailContent
157
+ if emailProperty.get('sender') != _parseEmailContent.get('sender'):
158
+ property_errors.append(
159
+ ["发件人断言失败", {"预期": emailProperty.get('sender'), "实际": _parseEmailContent.get('sender')}])
160
+ if emailProperty.get('receiveAddress') != _parseEmailContent.get('receiveAddress'):
161
+ property_errors.append(["回复邮箱断言失败",
162
+ {"预期": emailProperty.get('receiveAddress'),
163
+ "实际": _parseEmailContent.get('receiveAddress')}])
164
+ return property_errors
165
+
166
+
167
+ def getRandomHyperlinksInHtml(EmailContent):
168
+ """
169
+ 获取html中的随机超链接
170
+ @param html:
171
+ @return:
172
+ """
173
+ flag = 1
174
+ # page = BeautifulSoup(EmailContent[1], features="html.parser")
175
+ pages = BeautifulSoup(EmailContent[1], features="html.parser")
176
+ alinks = pages.findAll('a')
177
+ new_links = []
178
+ for url in alinks:
179
+ if url.get('href', None) != '#' and 'mailto:' not in url.get('href', None) and url.get('href',
180
+ None) is not None:
181
+ new_links.append(url.get('href', None))
182
+ # 随机拿一个
183
+ print(new_links)
184
+ url = new_links[random.randint(0, len(new_links) - 1)]
185
+ redirect_url = originalLinkGetsRedirectUrl(url)
186
+ # print("初始获取重定向后的链接:", redirect_url)
187
+ while 'unsubscribe' in redirect_url:
188
+ url = new_links[random.randint(0, len(new_links) - 1)]
189
+ redirect_url = originalLinkGetsRedirectUrl(url)
190
+ print("获取非退订包含utm链接:", originalLinkGetsRedirectUrl(url))
191
+ return url
192
+
193
+
194
+ def originalLinkGetsRedirectUrl(url):
195
+ """
196
+ 原始链接获取重定向后带有utm的链接
197
+ @param url:
198
+ @return:
199
+ """
200
+ global final_location_url
201
+ print(url)
202
+ try:
203
+ session = requests.session()
204
+ resp_1 = session.get(url, allow_redirects=True)
205
+ # print("第一次重定向:",resp_1.headers.get('Location'))
206
+ # location_url_1 = resp_1.headers.get('Location')
207
+ # resp_2 = session.get(location_url_1, allow_redirects=False)
208
+ # print("第二次重定向:",resp_2.headers.get('Location'))
209
+ # final_location_url = resp_2.headers.get('Location')
210
+ final_location_url = resp_1.url
211
+ return final_location_url
212
+ except:
213
+ raise
214
+
215
+
216
+ def parseUrlParameters(url):
217
+ """
218
+ 返回url后的拼接参数
219
+ @param url:
220
+ @return:
221
+ """
222
+ return parse_qs(requests.utils.urlparse(url).query)
223
+
224
+
225
+ def name_convert_to_snake(name: str) -> str:
226
+ """驼峰转下划线"""
227
+ if re.search(r'[^_][A-Z]', name):
228
+ name = re.sub(r'([^_])([A-Z][a-z]+)', r'\1_\2', name)
229
+ return name_convert_to_snake(name)
230
+ return name.lower()
231
+
232
+
233
+ def assertUtmConfig(emailProperty):
234
+ """
235
+ 断言utm
236
+ @param utmConfigInfo: 请求时存的utm参数
237
+ @param emailUtmConfig: 邮件内容获取的utm参数
238
+ @param activityId:
239
+ @return:
240
+ """
241
+ global EmailContentAll
242
+ for _email in emailProperty:
243
+ _subject = list(_email.keys())[0]
244
+ try:
245
+ UIDs = selectFolderGetUids(imapObj, allEmail, _subject)
246
+ assert UIDs
247
+ EmailContentAll = forParseEmailContent(UIDs, True)
248
+ except AssertionError:
249
+ UIDs = selectFolderGetUids(imapObj, junkEmail, _subject)
250
+ assert UIDs
251
+ EmailContentAll = forParseEmailContent(UIDs, True)
252
+ except Exception as e:
253
+ raise e
254
+ finally:
255
+ email = _email[_subject]
256
+ if email['utmConfigInfo'] is None:
257
+ print("--->测试邮件不进行utm校验")
258
+ break
259
+ temp = originalLinkGetsRedirectUrl(getRandomHyperlinksInHtml(EmailContentAll))
260
+ params = parseUrlParameters(temp)
261
+ for utmKey, utmValue in email['utmConfigInfo'].items():
262
+ assert params.get(name_convert_to_snake(utmKey))[0] == utmValue
263
+ # 断言sp参数
264
+ # ec1
265
+ if 'utm_term' in params:
266
+ utm_term = dict(parse.parse_qsl(params.get('utm_term')[0]))
267
+ _params = {**params, **utm_term}
268
+ params = _params
269
+ assert params.get('sp_medium') == 'email'
270
+ assert params.get('sp_source') == 'smartpush'
271
+ if email['activityId'] is not None:
272
+ assert params.get('sp_campaign') == str(email['activityId'])
273
+ # ec2
274
+ else:
275
+ assert params.get('sp_medium')[0] == 'email'
276
+ assert params.get('sp_source')[0] == 'smartpush'
277
+ if email['activityId'] is not None:
278
+ assert params.get('sp_campaign')[0] == str(email['activityId'])
279
+ # flow的断言需要另外写
280
+ print(f"UTM断言成功-->>{email['utmConfigInfo']} || {params} || {str(email['activityId'])}")
281
+
282
+
283
+ @retry(tries=3, delay=3, backoff=3, max_delay=20)
284
+ def check_email_content(emailProperty, loginEmail, password, **kwargs):
285
+ """
286
+ 校验邮件送达情况
287
+ loginEmail: 接收邮箱账号,必填
288
+ password: 邮箱密码,必填
289
+ emailProperty: list类型,格式: [{主旨: {receiveAddress: 回复邮箱, sender: 发件人}}], 必填
290
+
291
+ is_check_email_property: bool, 非必填,是否断言回复邮箱或发件人
292
+ is_check_utm: bool, 非必填,是否断言utm
293
+ """
294
+ global imapObj
295
+ try:
296
+ print("--->获取emailProperty变量", emailProperty)
297
+ imapObj = loginShowFoldersEmail(loginEmail, password)
298
+ result = assertEmail(emailProperty=emailProperty, **kwargs)
299
+ # assertUtmConfig(emailProperty)
300
+ return result
301
+ except Exception:
302
+ raise Exception
303
+ finally:
304
+ # 退出登录
305
+ imapObj.logout()
@@ -1,4 +1,4 @@
1
- def compare_lists(temp1, temp2, num=1):
1
+ def compare_lists(temp1, temp2, check_key=["completedCount"], all_key=False, num=1):
2
2
  """对比两个list中字典,a中字典对应的键值+num等于b字典中键值
3
3
  ab值示例:
4
4
  a = [{"123": {"a": 1, "b": 2}}, {"456": {"a": 5, "b": 6}}]
@@ -14,10 +14,14 @@ def compare_lists(temp1, temp2, num=1):
14
14
  # 获取内层字典
15
15
  inner_dict_a = temp1_a[outer_key]
16
16
  inner_dict_b = temp2_b[outer_key]
17
+ inner_dict_a_keys = list(inner_dict_a)
18
+ inner_dict_b_keys = list(inner_dict_b)
19
+ if all_key is False:
20
+ inner_dict_a_keys = inner_dict_b_keys = check_key
17
21
  # 遍历内层字典的键
18
- for inner_key in inner_dict_a:
22
+ for inner_key in inner_dict_a_keys:
19
23
  # 确保 temp2 对应的内层字典中也有相同的键
20
- if inner_key in inner_dict_b:
24
+ if inner_key in inner_dict_b_keys:
21
25
  # 检查是否满足条件
22
26
  if inner_dict_a[inner_key] + num != inner_dict_b[inner_key]:
23
27
  error.append({
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: smartpush
3
- Version: 1.3.8
3
+ Version: 1.4.0
4
4
  Summary: 用于smartpush自动化测试工具包
5
5
  Author: 卢泽彬、邵宇飞、周彦龙
6
6
 
@@ -1,18 +1,19 @@
1
1
  smartpush/__init__.py,sha256=XJrl1vhGATHSeSVqKmPXxYqxyseriUpvY5tLIXir3EE,24
2
2
  smartpush/get_jira_info.py,sha256=Ej2JRlO_Kct6Koju57b27ySy_B4q43f0I2bFcS_fmaw,17801
3
- smartpush/test.py,sha256=gOZE1am6-6ZPcfKLfh2KblHXhL5YY-LncPZhji4THYI,7648
3
+ smartpush/test.py,sha256=vY8VQTNmI0QZM0FFKqUZGbmZMbNs-DFKtMP4GZsfhbY,76739
4
4
  smartpush/export/__init__.py,sha256=D9GbWcmwnetEndFDty5XbVienFK1WjqV2yYcQp3CM84,99
5
5
  smartpush/export/basic/ExcelExportChecker.py,sha256=R_1gFy69vE2V5pY20zFsnhqWgJ42Vtf35zBtOPfhUpU,17590
6
6
  smartpush/export/basic/GetOssUrl.py,sha256=LeF1y1_uJaYXth1KvO6mEDS29ezb9tliBv5SrbqYkXc,6136
7
7
  smartpush/export/basic/ReadExcel.py,sha256=ZnG2mtYqLY-xuYx9SyulbdYUP_0E5jIeKDewfakAsTw,7342
8
8
  smartpush/export/basic/__init__.py,sha256=6tcrS-2NSlsJo-UwEsnGUmwCf7jgOsh_UEbM0FD-gYE,70
9
- smartpush/flow/MockFlow.py,sha256=I9EKR9-rQ6H-fI4dzYZ_WRrHqxVdIcxaPKGKzG_3e3I,5083
9
+ smartpush/flow/MockFlow.py,sha256=9suuzEWMWAOGF1uHZMcriMEgB2DfFkEzZWMeb55ufyI,6630
10
10
  smartpush/flow/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
11
11
  smartpush/utils/DataTypeUtils.py,sha256=BC7ioztO3vAfKd1EOoNvXdVuXYY8qjNskV1DP7LhW-M,1082
12
- smartpush/utils/ListDictUtils.py,sha256=OsmNzMA3nCAUJaRw53uyUkZI0t95VBlfxYwD4FFtjz8,1385
12
+ smartpush/utils/EmailUtlis.py,sha256=DAHd73bJ8hiJCLEXtD0xcwxPD7SOPSmBB7Jvlf6gN6s,11201
13
+ smartpush/utils/ListDictUtils.py,sha256=qXxpMwWoyaXwOHhSNUt55HtFfwmqli-wZTWmiP9qhsI,1657
13
14
  smartpush/utils/StringUtils.py,sha256=n8mo9k0JQN63MReImgv-66JxmmymOGknR8pH2fkQrAo,4139
14
15
  smartpush/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
15
- smartpush-1.3.8.dist-info/METADATA,sha256=8_OjDrX1Go1UcCFJO-VlEzcBHOlnIpVVmvxRiiRKCCs,145
16
- smartpush-1.3.8.dist-info/WHEEL,sha256=2wepM1nk4DS4eFpYrW1TTqPcoGNfHhhO_i5m4cOimbo,92
17
- smartpush-1.3.8.dist-info/top_level.txt,sha256=5_CXqu08EfbPaKLjuSAOAqCmGU6shiatwDU_ViBGCmg,10
18
- smartpush-1.3.8.dist-info/RECORD,,
16
+ smartpush-1.4.0.dist-info/METADATA,sha256=_UiAcwcgV8JAr2gsP9E1oIWti0f8mw37VGN71mcNl6g,145
17
+ smartpush-1.4.0.dist-info/WHEEL,sha256=2wepM1nk4DS4eFpYrW1TTqPcoGNfHhhO_i5m4cOimbo,92
18
+ smartpush-1.4.0.dist-info/top_level.txt,sha256=5_CXqu08EfbPaKLjuSAOAqCmGU6shiatwDU_ViBGCmg,10
19
+ smartpush-1.4.0.dist-info/RECORD,,