@churchapps/apihelper 0.0.1

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 (131) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +15 -0
  3. package/dist/auth/AuthenticatedUser.d.ts +17 -0
  4. package/dist/auth/AuthenticatedUser.d.ts.map +1 -0
  5. package/dist/auth/AuthenticatedUser.js +31 -0
  6. package/dist/auth/AuthenticatedUser.js.map +1 -0
  7. package/dist/auth/CustomAuthProvider.d.ts +7 -0
  8. package/dist/auth/CustomAuthProvider.d.ts.map +1 -0
  9. package/dist/auth/CustomAuthProvider.js +46 -0
  10. package/dist/auth/CustomAuthProvider.js.map +1 -0
  11. package/dist/auth/Principal.d.ts +9 -0
  12. package/dist/auth/Principal.d.ts.map +1 -0
  13. package/dist/auth/Principal.js +19 -0
  14. package/dist/auth/Principal.js.map +1 -0
  15. package/dist/auth/index.d.ts +4 -0
  16. package/dist/auth/index.d.ts.map +1 -0
  17. package/dist/auth/index.js +10 -0
  18. package/dist/auth/index.js.map +1 -0
  19. package/dist/controllers/CustomBaseController.d.ts +15 -0
  20. package/dist/controllers/CustomBaseController.d.ts.map +1 -0
  21. package/dist/controllers/CustomBaseController.js +83 -0
  22. package/dist/controllers/CustomBaseController.js.map +1 -0
  23. package/dist/controllers/ErrorController.d.ts +7 -0
  24. package/dist/controllers/ErrorController.d.ts.map +1 -0
  25. package/dist/controllers/ErrorController.js +63 -0
  26. package/dist/controllers/ErrorController.js.map +1 -0
  27. package/dist/controllers/index.d.ts +3 -0
  28. package/dist/controllers/index.d.ts.map +1 -0
  29. package/dist/controllers/index.js +8 -0
  30. package/dist/controllers/index.js.map +1 -0
  31. package/dist/helpers/AwsHelper.d.ts +13 -0
  32. package/dist/helpers/AwsHelper.d.ts.map +1 -0
  33. package/dist/helpers/AwsHelper.js +131 -0
  34. package/dist/helpers/AwsHelper.js.map +1 -0
  35. package/dist/helpers/BasePermissions.d.ts +31 -0
  36. package/dist/helpers/BasePermissions.d.ts.map +1 -0
  37. package/dist/helpers/BasePermissions.js +20 -0
  38. package/dist/helpers/BasePermissions.js.map +1 -0
  39. package/dist/helpers/DB.d.ts +8 -0
  40. package/dist/helpers/DB.d.ts.map +1 -0
  41. package/dist/helpers/DB.js +72 -0
  42. package/dist/helpers/DB.js.map +1 -0
  43. package/dist/helpers/DBCreator.d.ts +6 -0
  44. package/dist/helpers/DBCreator.d.ts.map +1 -0
  45. package/dist/helpers/DBCreator.js +56 -0
  46. package/dist/helpers/DBCreator.js.map +1 -0
  47. package/dist/helpers/EmailHelper.d.ts +7 -0
  48. package/dist/helpers/EmailHelper.d.ts.map +1 -0
  49. package/dist/helpers/EmailHelper.js +81 -0
  50. package/dist/helpers/EmailHelper.js.map +1 -0
  51. package/dist/helpers/EncryptionHelper.d.ts +6 -0
  52. package/dist/helpers/EncryptionHelper.d.ts.map +1 -0
  53. package/dist/helpers/EncryptionHelper.js +31 -0
  54. package/dist/helpers/EncryptionHelper.js.map +1 -0
  55. package/dist/helpers/EnvironmentBase.d.ts +17 -0
  56. package/dist/helpers/EnvironmentBase.d.ts.map +1 -0
  57. package/dist/helpers/EnvironmentBase.js +22 -0
  58. package/dist/helpers/EnvironmentBase.js.map +1 -0
  59. package/dist/helpers/FileStorageHelper.d.ts +15 -0
  60. package/dist/helpers/FileStorageHelper.d.ts.map +1 -0
  61. package/dist/helpers/FileStorageHelper.js +99 -0
  62. package/dist/helpers/FileStorageHelper.js.map +1 -0
  63. package/dist/helpers/Interfaces.d.ts +12 -0
  64. package/dist/helpers/Interfaces.d.ts.map +1 -0
  65. package/dist/helpers/Interfaces.js +3 -0
  66. package/dist/helpers/Interfaces.js.map +1 -0
  67. package/dist/helpers/LoggingHelper.d.ts +15 -0
  68. package/dist/helpers/LoggingHelper.d.ts.map +1 -0
  69. package/dist/helpers/LoggingHelper.js +83 -0
  70. package/dist/helpers/LoggingHelper.js.map +1 -0
  71. package/dist/helpers/MySqlHelper.d.ts +4 -0
  72. package/dist/helpers/MySqlHelper.d.ts.map +1 -0
  73. package/dist/helpers/MySqlHelper.js +10 -0
  74. package/dist/helpers/MySqlHelper.js.map +1 -0
  75. package/dist/helpers/OmitEmpty.d.ts +6 -0
  76. package/dist/helpers/OmitEmpty.d.ts.map +1 -0
  77. package/dist/helpers/OmitEmpty.js +94 -0
  78. package/dist/helpers/OmitEmpty.js.map +1 -0
  79. package/dist/helpers/Pool.d.ts +7 -0
  80. package/dist/helpers/Pool.d.ts.map +1 -0
  81. package/dist/helpers/Pool.js +55 -0
  82. package/dist/helpers/Pool.js.map +1 -0
  83. package/dist/helpers/index.d.ts +15 -0
  84. package/dist/helpers/index.d.ts.map +1 -0
  85. package/dist/helpers/index.js +31 -0
  86. package/dist/helpers/index.js.map +1 -0
  87. package/dist/index.d.ts +4 -0
  88. package/dist/index.d.ts.map +1 -0
  89. package/dist/index.js +20 -0
  90. package/dist/index.js.map +1 -0
  91. package/dist/models/ErrorLog.d.ts +7 -0
  92. package/dist/models/ErrorLog.d.ts.map +1 -0
  93. package/dist/models/ErrorLog.js +7 -0
  94. package/dist/models/ErrorLog.js.map +1 -0
  95. package/dist/models/index.d.ts +2 -0
  96. package/dist/models/index.d.ts.map +1 -0
  97. package/dist/models/index.js +6 -0
  98. package/dist/models/index.js.map +1 -0
  99. package/dist/tools/DBCreator.d.ts +1 -0
  100. package/dist/tools/DBCreator.d.ts.map +1 -0
  101. package/dist/tools/DBCreator.js +1 -0
  102. package/dist/tools/DBCreator.js.map +1 -0
  103. package/package.json +60 -0
  104. package/src/auth/AuthenticatedUser.ts +40 -0
  105. package/src/auth/CustomAuthProvider.ts +23 -0
  106. package/src/auth/Principal.ts +22 -0
  107. package/src/auth/index.ts +3 -0
  108. package/src/controllers/CustomBaseController.ts +74 -0
  109. package/src/controllers/ErrorController.ts +33 -0
  110. package/src/controllers/index.ts +2 -0
  111. package/src/helpers/AwsHelper.ts +108 -0
  112. package/src/helpers/BasePermissions.ts +15 -0
  113. package/src/helpers/DB.ts +41 -0
  114. package/src/helpers/DBCreator.ts +39 -0
  115. package/src/helpers/EmailHelper.ts +66 -0
  116. package/src/helpers/EncryptionHelper.ts +25 -0
  117. package/src/helpers/EnvironmentBase.ts +35 -0
  118. package/src/helpers/FileStorageHelper.ts +71 -0
  119. package/src/helpers/Interfaces.ts +2 -0
  120. package/src/helpers/LoggingHelper.ts +75 -0
  121. package/src/helpers/MySqlHelper.ts +5 -0
  122. package/src/helpers/OmitEmpty.ts +97 -0
  123. package/src/helpers/Pool.ts +55 -0
  124. package/src/helpers/index.ts +14 -0
  125. package/src/index.ts +3 -0
  126. package/src/models/ErrorLog.ts +7 -0
  127. package/src/models/index.ts +1 -0
  128. package/src/tools/DBCreator.ts +0 -0
  129. package/src/tools/templates/ChurchEmailTemplate.html +383 -0
  130. package/src/tools/templates/EmailTemplate.html +426 -0
  131. package/tsconfig.json +39 -0
@@ -0,0 +1,97 @@
1
+ // Based on https://www.npmjs.com/package/omit-empty
2
+ // The project appears to be abandoned, but needed modification to allow for empty arrays.
3
+
4
+ "use strict";
5
+
6
+ import typeOf from "kind-of";
7
+
8
+
9
+ export class OmitEmpty {
10
+ public static omitEmpty(obj: any, options = {}) {
11
+ const runtimeOpts = OmitEmpty._buildRuntimeOpts(options);
12
+
13
+ const omit = (value: any, opts: any) => {
14
+ if (Array.isArray(value)) {
15
+ value = value.map(v => omit(v, opts)).filter(v => !OmitEmpty.isEmpty(v, opts));
16
+ }
17
+
18
+ if (typeOf(value) === "object") {
19
+ const result: any = {};
20
+ for (const key of Object.keys(value)) {
21
+ if (!opts.excludedProperties.includes(key)) {
22
+ const val: any = omit(value[key], opts);
23
+ if (val !== void 0) {
24
+ result[key] = val;
25
+ }
26
+ }
27
+ }
28
+ value = result;
29
+ }
30
+
31
+ if (!OmitEmpty.isEmpty(value, opts)) {
32
+ return value;
33
+ }
34
+ };
35
+
36
+ const res = omit(obj, runtimeOpts);
37
+ if (res === void 0) {
38
+ return typeOf(obj) === "object" ? {} : res;
39
+ }
40
+ return res;
41
+ }
42
+
43
+
44
+ private static _buildRuntimeOpts(options: any = {}) {
45
+ return {
46
+ omitZero: options.omitZero || false,
47
+ omitEmptyArray: options.omitEmptyArray || false,
48
+ excludedProperties: options.excludedProperties || []
49
+ };
50
+ };
51
+
52
+ private static isEmpty(value: any, runtimeOpts: any) {
53
+ switch (typeOf(value)) {
54
+ case "null":
55
+ case "undefined":
56
+ return true;
57
+ case "boolean":
58
+ case "function":
59
+ case "date":
60
+ case "regexp":
61
+ return false;
62
+ case "string":
63
+ case "arguments":
64
+ return value.length === 0;
65
+ case "file":
66
+ case "map":
67
+ case "set":
68
+ return value.size === 0;
69
+ case "number":
70
+ return runtimeOpts.omitZero ? value === 0 : false;
71
+ case "error":
72
+ return value.message === "";
73
+ case "array":
74
+ if (runtimeOpts.omitEmptyArray) {
75
+ for (const ele of value) {
76
+ if (!OmitEmpty.isEmpty(ele, runtimeOpts)) {
77
+ return false;
78
+ }
79
+ }
80
+ return true;
81
+ } else {
82
+ return false;
83
+ }
84
+ case "object":
85
+ for (const key of Object.keys(value)) {
86
+ if (!OmitEmpty.isEmpty(value[key], runtimeOpts)) {
87
+ return false;
88
+ }
89
+ }
90
+ return true;
91
+ default: {
92
+ return true;
93
+ }
94
+ }
95
+ }
96
+
97
+ }
@@ -0,0 +1,55 @@
1
+ import dotenv from "dotenv";
2
+ import mysql from "mysql";
3
+ import { EnvironmentBase } from ".";
4
+
5
+ dotenv.config();
6
+
7
+ export class Pool {
8
+ public static current: mysql.Pool;
9
+
10
+ public static initPool() {
11
+ const config = this.getConfig(EnvironmentBase.connectionString);
12
+
13
+ Pool.current = mysql.createPool({
14
+ connectionLimit: 3,
15
+ host: config.host,
16
+ port: config.port,
17
+ database: config.database,
18
+ user: config.userName,
19
+ password: config.password,
20
+ multipleStatements: true,
21
+ waitForConnections: true,
22
+ queueLimit: 9999,
23
+ typeCast: function castField(field, useDefaultTypeCasting) {
24
+ // convert bit(1) to bool
25
+ if ((field.type === "BIT") && (field.length === 1)) {
26
+ try {
27
+ const bytes = field.buffer();
28
+ return (bytes[0] === 1);
29
+ } catch (e) { return false; }
30
+ }
31
+ return (useDefaultTypeCasting());
32
+ }
33
+ });
34
+ }
35
+
36
+ // a bit of a hack
37
+ private static getConfig = (connectionString: string) => {
38
+ // mysql://user:password@host:port/dbName
39
+ const firstSplit = connectionString.replace("mysql://", "").split("@");
40
+ const userPass = firstSplit[0].split(":");
41
+ const userName = userPass[0];
42
+ const password = userPass[1];
43
+
44
+ const hostDb = firstSplit[1].split("/");
45
+ const database = hostDb[1];
46
+ const hostPort = hostDb[0].split(':');
47
+ const host = hostPort[0];
48
+ const port = parseInt(hostPort[1], 0)
49
+
50
+ return { host, port, database, userName, password }
51
+
52
+ }
53
+
54
+ }
55
+
@@ -0,0 +1,14 @@
1
+ export * from "@churchapps/helpers";
2
+ export * from "./AwsHelper";
3
+ export * from "./DB";
4
+ export * from "./DBCreator";
5
+ export * from "./EncryptionHelper";
6
+ export * from "./EnvironmentBase";
7
+ export * from "./FileStorageHelper";
8
+ export * from "./Interfaces";
9
+ export * from "./LoggingHelper";
10
+ export * from "./OmitEmpty";
11
+ export * from "./BasePermissions";
12
+ export * from "./EmailHelper";
13
+ export * from "./MySqlHelper";
14
+ export * from "./Pool"
package/src/index.ts ADDED
@@ -0,0 +1,3 @@
1
+ export * from "./helpers";
2
+ export * from "./auth";
3
+ export * from "./controllers";
@@ -0,0 +1,7 @@
1
+
2
+ export class ErrorLog {
3
+ public application?: string;
4
+ public level?: string;
5
+ public message?: string;
6
+ public additionalDetails?: string;
7
+ }
@@ -0,0 +1 @@
1
+ export { ErrorLog } from "./ErrorLog";
File without changes
@@ -0,0 +1,383 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en" xmlns="http://www.w3.org/1999/xhtml" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office">
3
+
4
+ <head>
5
+ <meta charset="utf-8"> <!-- utf-8 works for most cases -->
6
+ <meta name="viewport" content="width=device-width"> <!-- Forcing initial-scale shouldn't be necessary -->
7
+ <meta http-equiv="X-UA-Compatible" content="IE=edge"> <!-- Use the latest (edge) version of IE rendering engine -->
8
+ <meta name="x-apple-disable-message-reformatting"> <!-- Disable auto-scale in iOS 10 Mail entirely -->
9
+ <title></title> <!-- The title tag shows in email notifications, like Android 4.4. -->
10
+
11
+ <link href="https://fonts.googleapis.com/css?family=Lato:300,400,700" rel="stylesheet">
12
+
13
+ <!-- CSS Reset : BEGIN -->
14
+ <style>
15
+ /* What it does: Remove spaces around the email design added by some email clients. */
16
+ /* Beware: It can remove the padding / margin and add a background color to the compose a reply window. */
17
+ html,
18
+ body {
19
+ margin: 0 auto !important;
20
+ padding: 0 !important;
21
+ height: 100% !important;
22
+ width: 100% !important;
23
+ background: #f1f1f1;
24
+ }
25
+
26
+ /* What it does: Stops email clients resizing small text. */
27
+ * {
28
+ -ms-text-size-adjust: 100%;
29
+ -webkit-text-size-adjust: 100%;
30
+ }
31
+
32
+ /* What it does: Centers email on Android 4.4 */
33
+ div[style*="margin: 16px 0"] {
34
+ margin: 0 !important;
35
+ }
36
+
37
+ /* What it does: Stops Outlook from adding extra spacing to tables. */
38
+ table,
39
+ td {
40
+ mso-table-lspace: 0pt !important;
41
+ mso-table-rspace: 0pt !important;
42
+ }
43
+
44
+ /* What it does: Fixes webkit padding issue. */
45
+ table {
46
+ border-spacing: 0 !important;
47
+ border-collapse: collapse !important;
48
+ table-layout: fixed !important;
49
+ margin: 0 auto !important;
50
+ }
51
+
52
+ /* What it does: Uses a better rendering method when resizing images in IE. */
53
+ img {
54
+ -ms-interpolation-mode: bicubic;
55
+ }
56
+
57
+ /* What it does: Prevents Windows 10 Mail from underlining links despite inline CSS. Styles for underlined links should be inline. */
58
+ a {
59
+ text-decoration: none;
60
+ }
61
+
62
+ /* What it does: A work-around for email clients meddling in triggered links. */
63
+ *[x-apple-data-detectors],
64
+ /* iOS */
65
+ .unstyle-auto-detected-links *,
66
+ .aBn {
67
+ border-bottom: 0 !important;
68
+ cursor: default !important;
69
+ color: inherit !important;
70
+ text-decoration: none !important;
71
+ font-size: inherit !important;
72
+ font-family: inherit !important;
73
+ font-weight: inherit !important;
74
+ line-height: inherit !important;
75
+ }
76
+
77
+ /* What it does: Prevents Gmail from displaying a download button on large, non-linked images. */
78
+ .a6S {
79
+ display: none !important;
80
+ opacity: 0.01 !important;
81
+ }
82
+
83
+ /* What it does: Prevents Gmail from changing the text color in conversation threads. */
84
+ .im {
85
+ color: inherit !important;
86
+ }
87
+
88
+ /* If the above doesn't work, add a .g-img class to any image in question. */
89
+ img.g-img+div {
90
+ display: none !important;
91
+ }
92
+
93
+ /* What it does: Removes right gutter in Gmail iOS app: https://github.com/TedGoas/Cerberus/issues/89 */
94
+ /* Create one of these media queries for each additional viewport size you'd like to fix */
95
+
96
+ /* iPhone 4, 4S, 5, 5S, 5C, and 5SE */
97
+ @media only screen and (min-device-width: 320px) and (max-device-width: 374px) {
98
+ u~div .email-container {
99
+ min-width: 320px !important;
100
+ }
101
+ }
102
+
103
+ /* iPhone 6, 6S, 7, 8, and X */
104
+ @media only screen and (min-device-width: 375px) and (max-device-width: 413px) {
105
+ u~div .email-container {
106
+ min-width: 375px !important;
107
+ }
108
+ }
109
+
110
+ /* iPhone 6+, 7+, and 8+ */
111
+ @media only screen and (min-device-width: 414px) {
112
+ u~div .email-container {
113
+ min-width: 414px !important;
114
+ }
115
+ }
116
+ </style>
117
+
118
+ <!-- CSS Reset : END -->
119
+
120
+ <!-- Progressive Enhancements : BEGIN -->
121
+ <style>
122
+ .primary {
123
+ background: #0288d1;
124
+ }
125
+
126
+ .bg_white {
127
+ background: #ffffff;
128
+ }
129
+
130
+ .bg_light {
131
+ background: #fafafa;
132
+ }
133
+
134
+ .bg_black {
135
+ background: #000000;
136
+ }
137
+
138
+ .bg_dark {
139
+ background: rgba(0, 0, 0, .8);
140
+ }
141
+
142
+ .email-section {
143
+ padding: 2.5em;
144
+ }
145
+
146
+ /*BUTTON*/
147
+ .btn {
148
+ padding: 10px 15px;
149
+ display: inline-block;
150
+ }
151
+
152
+ .btn.btn-primary {
153
+ border-radius: 5px;
154
+ background: #0288d1;
155
+ color: #ffffff;
156
+ }
157
+
158
+ .btn.btn-white {
159
+ border-radius: 5px;
160
+ background: #ffffff;
161
+ color: #000000;
162
+ }
163
+
164
+ .btn.btn-white-outline {
165
+ border-radius: 5px;
166
+ background: transparent;
167
+ border: 1px solid #fff;
168
+ color: #fff;
169
+ }
170
+
171
+ .btn.btn-black-outline {
172
+ border-radius: 0px;
173
+ background: transparent;
174
+ border: 2px solid #000;
175
+ color: #000;
176
+ font-weight: 700;
177
+ }
178
+
179
+ h1,
180
+ h2,
181
+ h3,
182
+ h4,
183
+ h5,
184
+ h6 {
185
+ font-family: 'Lato', sans-serif;
186
+ color: #000000;
187
+ margin-top: 0;
188
+ font-weight: 400;
189
+ }
190
+
191
+ body {
192
+ font-family: 'Lato', sans-serif;
193
+ font-weight: 400;
194
+ font-size: 15px;
195
+ line-height: 1.8;
196
+ color: rgba(0, 0, 0, .4);
197
+ }
198
+
199
+ a {
200
+ color: #0288d1;
201
+ }
202
+
203
+ table {}
204
+
205
+ /*LOGO*/
206
+
207
+ .logo h1 {
208
+ margin: 0;
209
+ }
210
+
211
+ .logo h1 a {
212
+ color: #0288d1;
213
+ font-size: 24px;
214
+ font-weight: 700;
215
+ font-family: 'Lato', sans-serif;
216
+ }
217
+
218
+ /*HERO*/
219
+ .hero {
220
+ position: relative;
221
+ z-index: 0;
222
+ }
223
+
224
+ .hero .text {
225
+ color: rgba(0, 0, 0, .3);
226
+ }
227
+
228
+ .hero .text h2 {
229
+ color: #000;
230
+ font-size: 40px;
231
+ margin-bottom: 0;
232
+ font-weight: 400;
233
+ line-height: 1.4;
234
+ }
235
+
236
+ .hero .text h3 {
237
+ font-size: 24px;
238
+ font-weight: 300;
239
+ }
240
+
241
+ .hero .text h2 span {
242
+ font-weight: 600;
243
+ color: #0288d1;
244
+ }
245
+
246
+
247
+ /*HEADING SECTION*/
248
+ .heading-section {}
249
+
250
+ .heading-section h2 {
251
+ color: #000000;
252
+ font-size: 28px;
253
+ margin-top: 0;
254
+ line-height: 1.4;
255
+ font-weight: 400;
256
+ }
257
+
258
+ .heading-section .subheading {
259
+ margin-bottom: 20px !important;
260
+ display: inline-block;
261
+ font-size: 13px;
262
+ text-transform: uppercase;
263
+ letter-spacing: 2px;
264
+ color: rgba(0, 0, 0, .4);
265
+ position: relative;
266
+ }
267
+
268
+ .heading-section .subheading::after {
269
+ position: absolute;
270
+ left: 0;
271
+ right: 0;
272
+ bottom: -10px;
273
+ content: '';
274
+ width: 100%;
275
+ height: 2px;
276
+ background: #0288d1;
277
+ margin: 0 auto;
278
+ }
279
+
280
+ .heading-section-white {
281
+ color: rgba(255, 255, 255, .8);
282
+ }
283
+
284
+ .heading-section-white h2 {
285
+ line-height: 1;
286
+ padding-bottom: 0;
287
+ }
288
+
289
+ .heading-section-white h2 {
290
+ color: #ffffff;
291
+ }
292
+
293
+ .heading-section-white .subheading {
294
+ margin-bottom: 0;
295
+ display: inline-block;
296
+ font-size: 13px;
297
+ text-transform: uppercase;
298
+ letter-spacing: 2px;
299
+ color: rgba(255, 255, 255, .4);
300
+ }
301
+
302
+
303
+ ul.social {
304
+ padding: 0;
305
+ }
306
+
307
+ ul.social li {
308
+ display: inline-block;
309
+ margin-right: 10px;
310
+ }
311
+
312
+ /*FOOTER*/
313
+
314
+ .footer {
315
+ border-top: 1px solid rgba(0, 0, 0, .05);
316
+ color: rgba(0, 0, 0, .5);
317
+ }
318
+
319
+ .footer .heading {
320
+ color: #000;
321
+ font-size: 20px;
322
+ }
323
+
324
+ .footer ul {
325
+ margin: 0;
326
+ padding: 0;
327
+ }
328
+
329
+ .footer ul li {
330
+ list-style: none;
331
+ margin-bottom: 10px;
332
+ }
333
+
334
+ .footer ul li a {
335
+ color: rgba(0, 0, 0, 1);
336
+ }
337
+
338
+
339
+ @media screen and (max-width: 500px) {}
340
+ </style>
341
+
342
+
343
+ </head>
344
+
345
+ <body width="100%" style="margin: 0; padding: 0 !important; mso-line-height-rule: exactly; background-color: #f1f1f1;">
346
+ <center style="width: 100%; background-color: #f1f1f1;">
347
+ <div style="display: none; font-size: 1px;max-height: 0px; max-width: 0px; opacity: 0; overflow: hidden; mso-hide: all; font-family: sans-serif;">
348
+ &zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;
349
+ </div>
350
+ <div style="max-width: 600px; margin: 0 auto;" class="email-container">
351
+ <!-- BEGIN BODY -->
352
+ <table align="center" role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%" style="margin: auto;">
353
+ <tr>
354
+ <td valign="top" class="bg_white" style="padding: 1em 2.5em 0 2.5em;">
355
+ <table role="presentation" border="0" cellpadding="0" cellspacing="0" width="100%">
356
+ <tr>
357
+ <td class="logo" style="text-align: center;">
358
+ <h1>{appLink}</h1>
359
+ </td>
360
+ </tr>
361
+ </table>
362
+ </td>
363
+ </tr><!-- end tr -->
364
+ <tr>
365
+ <td valign="middle" class="hero bg_white" style="padding: 2em 0 4em 0;">
366
+ <table>
367
+ <tr>
368
+ <td>
369
+ <div class="text" style="padding: 0 2.5em; text-align: center;">
370
+ {contents}
371
+ </div>
372
+ </td>
373
+ </tr>
374
+ </table>
375
+ </td>
376
+ </tr><!-- end tr -->
377
+ <!-- 1 Column Text + Button : END -->
378
+ </table>
379
+ </div>
380
+ </center>
381
+ </body>
382
+
383
+ </html>