mirror of https://github.com/abpframework/eventhub
Browse Source
Send email for new event creation, event reminder, and event registrationpull/21/head
committed by
GitHub
21 changed files with 5935 additions and 12 deletions
@ -0,0 +1,37 @@ |
|||
using Volo.Abp.TextTemplating; |
|||
|
|||
namespace EventHub.Emailing |
|||
{ |
|||
public class EmailTemplateDefinitionProvider : TemplateDefinitionProvider |
|||
{ |
|||
public override void Define(ITemplateDefinitionContext context) |
|||
{ |
|||
context.Add( |
|||
new TemplateDefinition( |
|||
EmailTemplates.EventRegistration |
|||
).WithVirtualFilePath( |
|||
"/Emailing/Templates/EventRegistration.tpl", |
|||
isInlineLocalized: true |
|||
) |
|||
); |
|||
|
|||
context.Add( |
|||
new TemplateDefinition( |
|||
EmailTemplates.EventReminder |
|||
).WithVirtualFilePath( |
|||
"/Emailing/Templates/EventReminder.tpl", |
|||
isInlineLocalized: true |
|||
) |
|||
); |
|||
|
|||
context.Add( |
|||
new TemplateDefinition( |
|||
EmailTemplates.NewEventCreated |
|||
).WithVirtualFilePath( |
|||
"/Emailing/Templates/NewEventCreated.tpl", |
|||
isInlineLocalized: true |
|||
) |
|||
); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,11 @@ |
|||
namespace EventHub.Emailing |
|||
{ |
|||
public static class EmailTemplates |
|||
{ |
|||
public const string EventRegistration = "EventHub.Event.Registration"; |
|||
|
|||
public const string EventReminder = "EventHub.Event.Reminder"; |
|||
|
|||
public const string NewEventCreated = "EventHub.Event.NewEventCreated"; |
|||
} |
|||
} |
|||
@ -0,0 +1,157 @@ |
|||
<html> |
|||
|
|||
<head> |
|||
<meta name="viewport" content="width=device-width"> |
|||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> |
|||
<title>Eventhub</title> |
|||
<style> |
|||
@media only screen and (max-width: 620px) { |
|||
table[class=mail-body] h1{ |
|||
font-size: 36px !important; |
|||
margin-bottom: 10px !important; |
|||
} |
|||
table[class=mail-body] .content { |
|||
padding: 0 !important; |
|||
} |
|||
table[class=mail-body] .container { |
|||
padding: 0 !important; |
|||
width: 100% !important; |
|||
} |
|||
table[class=mail-body] .main { |
|||
border-left-width: 0 !important; |
|||
border-radius: 0 !important; |
|||
border-right-width: 0 !important; |
|||
} |
|||
table[class=mail-body] td { |
|||
width: 100% !important; |
|||
float: left!important; |
|||
} |
|||
table[class=mail-body] td a.btn { |
|||
display: block !important; |
|||
text-align: center; |
|||
} |
|||
table[class=mail-body] td h2 { |
|||
margin: 10px 0 !important; |
|||
} |
|||
table[class=mail-body] td .cont { |
|||
padding: 30px !important; |
|||
} |
|||
} |
|||
</style> |
|||
</head> |
|||
|
|||
<body> |
|||
<table border="0" cellpadding="0" cellspacing="0" class="mail-body" style="background-color: #ffffff;width: 100%; font-size: 16px;line-height: 1.4;font-family: Arial, sans-serif;"> |
|||
<tbody> |
|||
<tr> |
|||
<td class="container" width="800" style="display: block;margin: 0 auto !important; max-width: 800px;padding: 10px;width: 800px;"> |
|||
<div class="content" style="box-sizing: border-box;display: block;margin: 0 auto;max-width: 800px;padding: 0px;"> |
|||
<div style="display: flex; padding-top: 1.5rem"> |
|||
|
|||
<h1 style="justify-content: center;margin-left: auto;margin-right: auto;align-content: center;">EventHub</h1> |
|||
|
|||
</div> |
|||
<!-- START CENTERED WHITE CONTAINER --> |
|||
<div style="display: flex;"> |
|||
|
|||
<h1 style="justify-content: center;margin-left: auto;margin-right: auto;align-content: center;">{{model.title}}</h1> |
|||
|
|||
</div> |
|||
<table class="main" style="background: #ffffff;border-radius: 3px; width: 100%;"> |
|||
<!-- START MAIN CONTENT AREA --> |
|||
<tbody> |
|||
<tr> |
|||
<td class="wrapper" width="800"> |
|||
<table class="main" style="background: #ffffff;border-radius: 3px;width: 100%;"> |
|||
<tbody> |
|||
<tr> |
|||
<td class="wrapper" width="800"> |
|||
<table border="0" cellpadding="0" cellspacing="0" style="border-collapse: separate; vertical-align: top;mso-table-lspace: 0pt;mso-table-rspace: 0pt;width: 100%; "> |
|||
<tbody> |
|||
<tr> |
|||
<td style="vertical-align: top;" width="100%"> |
|||
<div class="cont" style="background: #eeeeee; border-radius: 10px; padding: 40px; margin-top: 20px;"> |
|||
<table style="border-collapse: separate; vertical-align: top;mso-table-lspace: 0pt;mso-table-rspace: 0pt;width: 100%; "> |
|||
<tbody> |
|||
<tr> |
|||
<td width="100%" style="vertical-align: top; font-size: 16px; font-family: Arial, sans-serif; color: #444; margin-top: 20px; margin-bottom: 20px; line-height: 1.75"> |
|||
<p> |
|||
Hi, |
|||
</p> |
|||
<p> |
|||
Great news! You attended the "{{model.title}}" event. |
|||
</p> |
|||
<div> |
|||
<table border="0" cellpadding="0" cellspacing="0" style=" border-collapse: separate; vertical-align: top; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: 100%;"> |
|||
<tbody> |
|||
<tr style="text-align: center"> |
|||
<td style="vertical-align: top;"> |
|||
|
|||
<p style="font-size: 13px; font-family: Arial, sans-serif; color: #777777; margin: 0; margin-top: 30px;">Start Time</p> |
|||
<p style="font-size: 21px; font-family: Arial, sans-serif; color: #444444; margin-bottom: 30px; margin-top: 6px;">{{model.start_time}}</p> |
|||
</td> |
|||
<td style="vertical-align: top;"> |
|||
|
|||
<p style="font-size: 13px; font-family: Arial, sans-serif; color: #777777; margin: 0; margin-top: 30px;">End Time</p> |
|||
<p style="font-size: 21px; font-family: Arial, sans-serif; color: #444444; margin-bottom: 30px; margin-top: 6px;">{{model.end_time}}</p> |
|||
</td> |
|||
|
|||
</tr> |
|||
</tbody> |
|||
</table> |
|||
<p style="margin-bottom: 20px; margin-top: 20px; text-align: center;"> |
|||
<a href="/events/{{model.url}}" class="btn" target="_blank" style="padding: 15px; background: #e90052; border-radius: 40px; text-align: center; color: white; font-weight: bold; text-decoration: none; font-size: 18px; padding-left: 45px; padding-right: 45px;">Event Details</a> |
|||
</p> |
|||
</div> |
|||
|
|||
<p style="font-size: 16px; font-family: Arial, sans-serif; color: #444; margin-top: 20px; margin-bottom: 0px;"> |
|||
Thank you,<br> EventHub |
|||
</p> |
|||
</td> |
|||
</tr> |
|||
</tbody> |
|||
</table> |
|||
</div> |
|||
</td> |
|||
</tr> |
|||
</tbody> |
|||
</table> |
|||
</td> |
|||
</tr> |
|||
</tbody> |
|||
</table> |
|||
|
|||
</td> |
|||
</tr> |
|||
</tbody> |
|||
</table> |
|||
<!-- START FOOTER --> |
|||
<table border="0" cellpadding="0" cellspacing="0" style="border-collapse: separate; vertical-align: top;mso-table-lspace: 0pt;mso-table-rspace: 0pt;width: 100%;"> |
|||
<tbody> |
|||
<tr> |
|||
<td class="content-block" style="vertical-align: top;" width="800"> |
|||
<div class="cont" style="background: #ffffff;border-top: 2px solid #eee; padding: 35px 40px 5px; margin-top: 0px; text-align: center;"> |
|||
<a href="https://eventhub.abp.io/" style="font-size: 16px; font-family: Arial, sans-serif; color: #777; font-weight: bold; margin-right: 30px; text-decoration: none;">Home</a> |
|||
</div> |
|||
</td> |
|||
</tr> |
|||
<tr> |
|||
<td class="content-block powered-by" style="vertical-align: top;" width="100%"> |
|||
<div class="cont" style="background: #ffffff; border-radius: 10px; padding: 5px 40px; margin-top: 10px; margin-bottom: 50px; text-align: center;"> |
|||
<a href="mailto:info@eventhub.abp.io" style="font-size: 16px; font-family: Arial, sans-serif; color: #777; font-weight: bold; margin-right: 30px; text-decoration: none;"><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAARCAYAAADHeGwwAAABMElEQVQ4je3TvyvFYRQG8M+9LEwWiV0xyeAi2ZTUFQuZDAqTxUCJzY9BFotS/gAySAZFEgYlySzFLosfs169w6XL/V6uzbO973vO85z3OeekstlsGRYxrrTYw1g56jGNO6yivAQyS5hFdRpHGMQauvDwC+IXDGAGnTgJApXYxAJO0YLrH5Dfog3bmMAhatI5AUF1B4/oiIFJcYAMbrCRa3X6E0EvzlEbbZtLILCMHlQESzCS+/hZIKARF7Ef8+jDc564VwxhCq24jL/4gHwCAVXYxyR2o7e3Oe/30cbQuzEcB7/zEX03kkF8BU2RJFS3hVS07wnrGP2GI9HMD6MB/eiOd9Wx6vZCyUmXKhM9Hojn8JO6JInFbG2YrLMi4t/xVZNLhn+BgghNvkLzn7Bz9QbIADMmEt9imAAAAABJRU5ErkJggg==" width="16"> info@eventhub.abp.io</a> |
|||
<span style="font-size: 16px; font-family: Arial, sans-serif; color: #777; margin-right: 0px; text-decoration: none;"><strong>EventHub</strong> - Powered by Volosoft</span> |
|||
</div> |
|||
</td> |
|||
</tr> |
|||
</tbody> |
|||
</table> |
|||
</div> |
|||
<!-- END FOOTER --> |
|||
<!-- END CENTERED WHITE CONTAINER --> |
|||
</td> |
|||
</tr> |
|||
</tbody> |
|||
</table> |
|||
</body> |
|||
|
|||
</html> |
|||
@ -0,0 +1,157 @@ |
|||
<html> |
|||
|
|||
<head> |
|||
<meta name="viewport" content="width=device-width"> |
|||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> |
|||
<title>Eventhub</title> |
|||
<style> |
|||
@media only screen and (max-width: 620px) { |
|||
table[class=mail-body] h1{ |
|||
font-size: 36px !important; |
|||
margin-bottom: 10px !important; |
|||
} |
|||
table[class=mail-body] .content { |
|||
padding: 0 !important; |
|||
} |
|||
table[class=mail-body] .container { |
|||
padding: 0 !important; |
|||
width: 100% !important; |
|||
} |
|||
table[class=mail-body] .main { |
|||
border-left-width: 0 !important; |
|||
border-radius: 0 !important; |
|||
border-right-width: 0 !important; |
|||
} |
|||
table[class=mail-body] td { |
|||
width: 100% !important; |
|||
float: left!important; |
|||
} |
|||
table[class=mail-body] td a.btn { |
|||
display: block !important; |
|||
text-align: center; |
|||
} |
|||
table[class=mail-body] td h2 { |
|||
margin: 10px 0 !important; |
|||
} |
|||
table[class=mail-body] td .cont { |
|||
padding: 30px !important; |
|||
} |
|||
} |
|||
</style> |
|||
</head> |
|||
|
|||
<body> |
|||
<table border="0" cellpadding="0" cellspacing="0" class="mail-body" style="background-color: #ffffff;width: 100%; font-size: 16px;line-height: 1.4;font-family: Arial, sans-serif;"> |
|||
<tbody> |
|||
<tr> |
|||
<td class="container" width="800" style="display: block;margin: 0 auto !important; max-width: 800px;padding: 10px;width: 800px;"> |
|||
<div class="content" style="box-sizing: border-box;display: block;margin: 0 auto;max-width: 800px;padding: 0px;"> |
|||
<div style="display: flex; padding-top: 1.5rem"> |
|||
|
|||
<h1 style="justify-content: center;margin-left: auto;margin-right: auto;align-content: center;">EventHub</h1> |
|||
|
|||
</div> |
|||
<!-- START CENTERED WHITE CONTAINER --> |
|||
<div style="display: flex;"> |
|||
|
|||
<h1 style="justify-content: center;margin-left: auto;margin-right: auto;align-content: center;">{{model.title}} event will start soon</h1> |
|||
|
|||
</div> |
|||
<table class="main" style="background: #ffffff;border-radius: 3px; width: 100%;"> |
|||
<!-- START MAIN CONTENT AREA --> |
|||
<tbody> |
|||
<tr> |
|||
<td class="wrapper" width="800"> |
|||
<table class="main" style="background: #ffffff;border-radius: 3px;width: 100%;"> |
|||
<tbody> |
|||
<tr> |
|||
<td class="wrapper" width="800"> |
|||
<table border="0" cellpadding="0" cellspacing="0" style="border-collapse: separate; vertical-align: top;mso-table-lspace: 0pt;mso-table-rspace: 0pt;width: 100%; "> |
|||
<tbody> |
|||
<tr> |
|||
<td style="vertical-align: top;" width="100%"> |
|||
<div class="cont" style="background: #eeeeee; border-radius: 10px; padding: 40px; margin-top: 20px;"> |
|||
<table style="border-collapse: separate; vertical-align: top;mso-table-lspace: 0pt;mso-table-rspace: 0pt;width: 100%; "> |
|||
<tbody> |
|||
<tr> |
|||
<td width="100%" style="vertical-align: top; font-size: 16px; font-family: Arial, sans-serif; color: #444; margin-top: 20px; margin-bottom: 20px; line-height: 1.75"> |
|||
<p> |
|||
Hi {{model.user_name}}, |
|||
</p> |
|||
<p> |
|||
The "{{model.title}}" event will start very soon. |
|||
</p> |
|||
<div> |
|||
<table border="0" cellpadding="0" cellspacing="0" style=" border-collapse: separate; vertical-align: top; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: 100%;"> |
|||
<tbody> |
|||
<tr style="text-align: center"> |
|||
<td style="vertical-align: top;"> |
|||
|
|||
<p style="font-size: 13px; font-family: Arial, sans-serif; color: #777777; margin: 0; margin-top: 30px;">Start Time</p> |
|||
<p style="font-size: 21px; font-family: Arial, sans-serif; color: #444444; margin-bottom: 30px; margin-top: 6px;">{{model.start_time}}</p> |
|||
</td> |
|||
<td style="vertical-align: top;"> |
|||
|
|||
<p style="font-size: 13px; font-family: Arial, sans-serif; color: #777777; margin: 0; margin-top: 30px;">End Time</p> |
|||
<p style="font-size: 21px; font-family: Arial, sans-serif; color: #444444; margin-bottom: 30px; margin-top: 6px;">{{model.end_time}}</p> |
|||
</td> |
|||
|
|||
</tr> |
|||
</tbody> |
|||
</table> |
|||
<p style="margin-bottom: 20px; margin-top: 20px; text-align: center;"> |
|||
<a href="/events/{{model.url}}" class="btn" target="_blank" style="padding: 15px; background: #e90052; border-radius: 40px; text-align: center; color: white; font-weight: bold; text-decoration: none; font-size: 18px; padding-left: 45px; padding-right: 45px;">Event Details</a> |
|||
</p> |
|||
</div> |
|||
|
|||
<p style="font-size: 16px; font-family: Arial, sans-serif; color: #444; margin-top: 20px; margin-bottom: 0px;"> |
|||
Thank you,<br> EventHub |
|||
</p> |
|||
</td> |
|||
</tr> |
|||
</tbody> |
|||
</table> |
|||
</div> |
|||
</td> |
|||
</tr> |
|||
</tbody> |
|||
</table> |
|||
</td> |
|||
</tr> |
|||
</tbody> |
|||
</table> |
|||
|
|||
</td> |
|||
</tr> |
|||
</tbody> |
|||
</table> |
|||
<!-- START FOOTER --> |
|||
<table border="0" cellpadding="0" cellspacing="0" style="border-collapse: separate; vertical-align: top;mso-table-lspace: 0pt;mso-table-rspace: 0pt;width: 100%;"> |
|||
<tbody> |
|||
<tr> |
|||
<td class="content-block" style="vertical-align: top;" width="800"> |
|||
<div class="cont" style="background: #ffffff;border-top: 2px solid #eee; padding: 35px 40px 5px; margin-top: 0px; text-align: center;"> |
|||
<a href="https://eventhub.abp.io/" style="font-size: 16px; font-family: Arial, sans-serif; color: #777; font-weight: bold; margin-right: 30px; text-decoration: none;">Home</a> |
|||
</div> |
|||
</td> |
|||
</tr> |
|||
<tr> |
|||
<td class="content-block powered-by" style="vertical-align: top;" width="100%"> |
|||
<div class="cont" style="background: #ffffff; border-radius: 10px; padding: 5px 40px; margin-top: 10px; margin-bottom: 50px; text-align: center;"> |
|||
<a href="mailto:info@eventhub.abp.io" style="font-size: 16px; font-family: Arial, sans-serif; color: #777; font-weight: bold; margin-right: 30px; text-decoration: none;"><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAARCAYAAADHeGwwAAABMElEQVQ4je3TvyvFYRQG8M+9LEwWiV0xyeAi2ZTUFQuZDAqTxUCJzY9BFotS/gAySAZFEgYlySzFLosfs169w6XL/V6uzbO973vO85z3OeekstlsGRYxrrTYw1g56jGNO6yivAQyS5hFdRpHGMQauvDwC+IXDGAGnTgJApXYxAJO0YLrH5Dfog3bmMAhatI5AUF1B4/oiIFJcYAMbrCRa3X6E0EvzlEbbZtLILCMHlQESzCS+/hZIKARF7Ef8+jDc564VwxhCq24jL/4gHwCAVXYxyR2o7e3Oe/30cbQuzEcB7/zEX03kkF8BU2RJFS3hVS07wnrGP2GI9HMD6MB/eiOd9Wx6vZCyUmXKhM9Hojn8JO6JInFbG2YrLMi4t/xVZNLhn+BgghNvkLzn7Bz9QbIADMmEt9imAAAAABJRU5ErkJggg==" width="16"> info@eventhub.abp.io</a> |
|||
<span style="font-size: 16px; font-family: Arial, sans-serif; color: #777; margin-right: 0px; text-decoration: none;"><strong>EventHub</strong> - Powered by Volosoft</span> |
|||
</div> |
|||
</td> |
|||
</tr> |
|||
</tbody> |
|||
</table> |
|||
</div> |
|||
<!-- END FOOTER --> |
|||
<!-- END CENTERED WHITE CONTAINER --> |
|||
</td> |
|||
</tr> |
|||
</tbody> |
|||
</table> |
|||
</body> |
|||
|
|||
</html> |
|||
@ -0,0 +1,157 @@ |
|||
<html> |
|||
|
|||
<head> |
|||
<meta name="viewport" content="width=device-width"> |
|||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> |
|||
<title>Eventhub</title> |
|||
<style> |
|||
@media only screen and (max-width: 620px) { |
|||
table[class=mail-body] h1{ |
|||
font-size: 36px !important; |
|||
margin-bottom: 10px !important; |
|||
} |
|||
table[class=mail-body] .content { |
|||
padding: 0 !important; |
|||
} |
|||
table[class=mail-body] .container { |
|||
padding: 0 !important; |
|||
width: 100% !important; |
|||
} |
|||
table[class=mail-body] .main { |
|||
border-left-width: 0 !important; |
|||
border-radius: 0 !important; |
|||
border-right-width: 0 !important; |
|||
} |
|||
table[class=mail-body] td { |
|||
width: 100% !important; |
|||
float: left!important; |
|||
} |
|||
table[class=mail-body] td a.btn { |
|||
display: block !important; |
|||
text-align: center; |
|||
} |
|||
table[class=mail-body] td h2 { |
|||
margin: 10px 0 !important; |
|||
} |
|||
table[class=mail-body] td .cont { |
|||
padding: 30px !important; |
|||
} |
|||
} |
|||
</style> |
|||
</head> |
|||
|
|||
<body> |
|||
<table border="0" cellpadding="0" cellspacing="0" class="mail-body" style="background-color: #ffffff;width: 100%; font-size: 16px;line-height: 1.4;font-family: Arial, sans-serif;"> |
|||
<tbody> |
|||
<tr> |
|||
<td class="container" width="800" style="display: block;margin: 0 auto !important; max-width: 800px;padding: 10px;width: 800px;"> |
|||
<div class="content" style="box-sizing: border-box;display: block;margin: 0 auto;max-width: 800px;padding: 0px;"> |
|||
<div style="display: flex; padding-top: 1.5rem"> |
|||
|
|||
<h1 style="justify-content: center;margin-left: auto;margin-right: auto;align-content: center;">EventHub</h1> |
|||
|
|||
</div> |
|||
<!-- START CENTERED WHITE CONTAINER --> |
|||
<div style="display: flex;"> |
|||
|
|||
<h1 style="justify-content: center;margin-left: auto;margin-right: auto;align-content: center;">There is a new event that may interest you</h1> |
|||
|
|||
</div> |
|||
<table class="main" style="background: #ffffff;border-radius: 3px; width: 100%;"> |
|||
<!-- START MAIN CONTENT AREA --> |
|||
<tbody> |
|||
<tr> |
|||
<td class="wrapper" width="800"> |
|||
<table class="main" style="background: #ffffff;border-radius: 3px;width: 100%;"> |
|||
<tbody> |
|||
<tr> |
|||
<td class="wrapper" width="800"> |
|||
<table border="0" cellpadding="0" cellspacing="0" style="border-collapse: separate; vertical-align: top;mso-table-lspace: 0pt;mso-table-rspace: 0pt;width: 100%; "> |
|||
<tbody> |
|||
<tr> |
|||
<td style="vertical-align: top;" width="100%"> |
|||
<div class="cont" style="background: #eeeeee; border-radius: 10px; padding: 40px; margin-top: 20px;"> |
|||
<table style="border-collapse: separate; vertical-align: top;mso-table-lspace: 0pt;mso-table-rspace: 0pt;width: 100%; "> |
|||
<tbody> |
|||
<tr> |
|||
<td width="100%" style="vertical-align: top; font-size: 16px; font-family: Arial, sans-serif; color: #444; margin-top: 20px; margin-bottom: 20px; line-height: 1.75"> |
|||
<p> |
|||
Hi {{model.user_name}}, |
|||
</p> |
|||
<p> |
|||
A new event called "{{model.title}}" has been created. |
|||
</p> |
|||
<div> |
|||
<table border="0" cellpadding="0" cellspacing="0" style=" border-collapse: separate; vertical-align: top; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: 100%;"> |
|||
<tbody> |
|||
<tr style="text-align: center"> |
|||
<td style="vertical-align: top;"> |
|||
|
|||
<p style="font-size: 13px; font-family: Arial, sans-serif; color: #777777; margin: 0; margin-top: 30px;">Start Time</p> |
|||
<p style="font-size: 21px; font-family: Arial, sans-serif; color: #444444; margin-bottom: 30px; margin-top: 6px;">{{model.start_time}}</p> |
|||
</td> |
|||
<td style="vertical-align: top;"> |
|||
|
|||
<p style="font-size: 13px; font-family: Arial, sans-serif; color: #777777; margin: 0; margin-top: 30px;">End Time</p> |
|||
<p style="font-size: 21px; font-family: Arial, sans-serif; color: #444444; margin-bottom: 30px; margin-top: 6px;">{{model.end_time}}</p> |
|||
</td> |
|||
|
|||
</tr> |
|||
</tbody> |
|||
</table> |
|||
<p style="margin-bottom: 20px; margin-top: 20px; text-align: center;"> |
|||
<a href="/events/{{model.url}}" class="btn" target="_blank" style="padding: 15px; background: #e90052; border-radius: 40px; text-align: center; color: white; font-weight: bold; text-decoration: none; font-size: 18px; padding-left: 45px; padding-right: 45px;">Event Details</a> |
|||
</p> |
|||
</div> |
|||
|
|||
<p style="font-size: 16px; font-family: Arial, sans-serif; color: #444; margin-top: 20px; margin-bottom: 0px;"> |
|||
Thank you,<br> EventHub |
|||
</p> |
|||
</td> |
|||
</tr> |
|||
</tbody> |
|||
</table> |
|||
</div> |
|||
</td> |
|||
</tr> |
|||
</tbody> |
|||
</table> |
|||
</td> |
|||
</tr> |
|||
</tbody> |
|||
</table> |
|||
|
|||
</td> |
|||
</tr> |
|||
</tbody> |
|||
</table> |
|||
<!-- START FOOTER --> |
|||
<table border="0" cellpadding="0" cellspacing="0" style="border-collapse: separate; vertical-align: top;mso-table-lspace: 0pt;mso-table-rspace: 0pt;width: 100%;"> |
|||
<tbody> |
|||
<tr> |
|||
<td class="content-block" style="vertical-align: top;" width="800"> |
|||
<div class="cont" style="background: #ffffff;border-top: 2px solid #eee; padding: 35px 40px 5px; margin-top: 0px; text-align: center;"> |
|||
<a href="https://eventhub.abp.io/" style="font-size: 16px; font-family: Arial, sans-serif; color: #777; font-weight: bold; margin-right: 30px; text-decoration: none;">Home</a> |
|||
</div> |
|||
</td> |
|||
</tr> |
|||
<tr> |
|||
<td class="content-block powered-by" style="vertical-align: top;" width="100%"> |
|||
<div class="cont" style="background: #ffffff; border-radius: 10px; padding: 5px 40px; margin-top: 10px; margin-bottom: 50px; text-align: center;"> |
|||
<a href="mailto:info@eventhub.abp.io" style="font-size: 16px; font-family: Arial, sans-serif; color: #777; font-weight: bold; margin-right: 30px; text-decoration: none;"><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAARCAYAAADHeGwwAAABMElEQVQ4je3TvyvFYRQG8M+9LEwWiV0xyeAi2ZTUFQuZDAqTxUCJzY9BFotS/gAySAZFEgYlySzFLosfs169w6XL/V6uzbO973vO85z3OeekstlsGRYxrrTYw1g56jGNO6yivAQyS5hFdRpHGMQauvDwC+IXDGAGnTgJApXYxAJO0YLrH5Dfog3bmMAhatI5AUF1B4/oiIFJcYAMbrCRa3X6E0EvzlEbbZtLILCMHlQESzCS+/hZIKARF7Ef8+jDc564VwxhCq24jL/4gHwCAVXYxyR2o7e3Oe/30cbQuzEcB7/zEX03kkF8BU2RJFS3hVS07wnrGP2GI9HMD6MB/eiOd9Wx6vZCyUmXKhM9Hojn8JO6JInFbG2YrLMi4t/xVZNLhn+BgghNvkLzn7Bz9QbIADMmEt9imAAAAABJRU5ErkJggg==" width="16"> info@eventhub.abp.io</a> |
|||
<span style="font-size: 16px; font-family: Arial, sans-serif; color: #777; margin-right: 0px; text-decoration: none;"><strong>EventHub</strong> - Powered by Volosoft</span> |
|||
</div> |
|||
</td> |
|||
</tr> |
|||
</tbody> |
|||
</table> |
|||
</div> |
|||
<!-- END FOOTER --> |
|||
<!-- END CENTERED WHITE CONTAINER --> |
|||
</td> |
|||
</tr> |
|||
</tbody> |
|||
</table> |
|||
</body> |
|||
|
|||
</html> |
|||
@ -0,0 +1,73 @@ |
|||
using System; |
|||
using System.Linq; |
|||
using System.Threading.Tasks; |
|||
using EventHub.Emailing; |
|||
using EventHub.Events.Registrations; |
|||
using EventHub.Users; |
|||
using Volo.Abp.DependencyInjection; |
|||
using Volo.Abp.Domain.Repositories; |
|||
using Volo.Abp.Emailing; |
|||
using Volo.Abp.Linq; |
|||
using Volo.Abp.TextTemplating; |
|||
|
|||
namespace EventHub.Events |
|||
{ |
|||
public class EventReminderNotifier : ITransientDependency |
|||
{ |
|||
private readonly IEmailSender _emailSender; |
|||
private readonly ITemplateRenderer _templateRenderer; |
|||
private readonly IRepository<AppUser, Guid> _userRepository; |
|||
private readonly IRepository<EventRegistration, Guid> _eventRegistrationRepository; |
|||
private readonly IAsyncQueryableExecuter _asyncExecuter; |
|||
|
|||
public EventReminderNotifier( |
|||
IEmailSender emailSender, |
|||
ITemplateRenderer templateRenderer, |
|||
IRepository<AppUser, Guid> userRepository, |
|||
IRepository<EventRegistration, Guid> eventRegistrationRepository, |
|||
IAsyncQueryableExecuter asyncExecuter) |
|||
{ |
|||
_emailSender = emailSender; |
|||
_templateRenderer = templateRenderer; |
|||
_userRepository = userRepository; |
|||
_eventRegistrationRepository = eventRegistrationRepository; |
|||
_asyncExecuter = asyncExecuter; |
|||
} |
|||
|
|||
public async Task NotifyAsync(Event @event) |
|||
{ |
|||
if (@event is null) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
var userQueryable = await _userRepository.GetQueryableAsync(); |
|||
var eventRegistrationQueryable = await _eventRegistrationRepository.GetQueryableAsync(); |
|||
|
|||
var userQuery = from eventRegistration in eventRegistrationQueryable |
|||
join user in userQueryable on eventRegistration.UserId equals user.Id |
|||
where eventRegistration.EventId == @event.Id |
|||
select user; |
|||
|
|||
var usersToBeNotified = await _asyncExecuter.ToListAsync(userQuery); |
|||
|
|||
foreach (var user in usersToBeNotified) |
|||
{ |
|||
var model = new |
|||
{ |
|||
UserName = user.GetFullNameOrUsername(), |
|||
Title = @event.Title, |
|||
StartTime = @event.StartTime, |
|||
EndTime = @event.EndTime, |
|||
Url = @event.Url |
|||
}; |
|||
|
|||
await _emailSender.QueueAsync( |
|||
user.Email, |
|||
"The event has last thirty minutes to start!", |
|||
await _templateRenderer.RenderAsync(EmailTemplates.EventReminder, model) |
|||
); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,57 @@ |
|||
using System; |
|||
using System.Linq; |
|||
using System.Threading.Tasks; |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using Microsoft.Extensions.Logging; |
|||
using Volo.Abp.BackgroundWorkers; |
|||
using Volo.Abp.Domain.Repositories; |
|||
using Volo.Abp.Linq; |
|||
using Volo.Abp.Threading; |
|||
using Volo.Abp.Uow; |
|||
|
|||
namespace EventHub.Events |
|||
{ |
|||
public class EventReminderWorker : AsyncPeriodicBackgroundWorkerBase |
|||
{ |
|||
public EventReminderWorker(AbpAsyncTimer timer, IServiceScopeFactory serviceScopeFactory) |
|||
: base(timer, serviceScopeFactory) |
|||
{ |
|||
Timer.Period = 60_000; |
|||
} |
|||
|
|||
[UnitOfWork] |
|||
protected override async Task DoWorkAsync(PeriodicBackgroundWorkerContext workerContext) |
|||
{ |
|||
var eventReminderNotifier = workerContext.ServiceProvider.GetRequiredService<EventReminderNotifier>(); |
|||
var eventRepository = workerContext.ServiceProvider.GetRequiredService<IRepository<Event, Guid>>(); |
|||
var asyncExecuter = workerContext.ServiceProvider.GetRequiredService<IAsyncQueryableExecuter>(); |
|||
|
|||
var eventQueryable = await eventRepository.GetQueryableAsync(); |
|||
|
|||
var thirtyMinutesAfter = DateTime.Now.AddMinutes(30); |
|||
var oneMinutesAfter = DateTime.Now.AddMinutes(1); |
|||
|
|||
var eventQuery = eventQueryable.Where(x => |
|||
x.IsRemindingEmailSent == false && |
|||
x.StartTime <= thirtyMinutesAfter && |
|||
x.StartTime >= oneMinutesAfter); |
|||
|
|||
var events = await asyncExecuter.ToListAsync(eventQuery); |
|||
|
|||
foreach (var @event in events) |
|||
{ |
|||
try |
|||
{ |
|||
await eventReminderNotifier.NotifyAsync(@event); |
|||
@event.IsRemindingEmailSent = true; |
|||
} |
|||
catch (Exception e) |
|||
{ |
|||
@event.IsRemindingEmailSent = false; |
|||
Logger.LogError( |
|||
$"An error occurred while sending reminder mail for {@event.Id} event. Error message: {e.Message}"); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,50 @@ |
|||
using System; |
|||
using System.Linq; |
|||
using System.Threading.Tasks; |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using Microsoft.Extensions.Logging; |
|||
using Volo.Abp.BackgroundWorkers; |
|||
using Volo.Abp.Domain.Repositories; |
|||
using Volo.Abp.Linq; |
|||
using Volo.Abp.Threading; |
|||
using Volo.Abp.Uow; |
|||
|
|||
namespace EventHub.Events |
|||
{ |
|||
public class NewEventDetectorWorker : AsyncPeriodicBackgroundWorkerBase |
|||
{ |
|||
public NewEventDetectorWorker(AbpAsyncTimer timer, IServiceScopeFactory serviceScopeFactory) |
|||
: base(timer, serviceScopeFactory) |
|||
{ |
|||
Timer.Period = 60_000; |
|||
} |
|||
|
|||
[UnitOfWork] |
|||
protected override async Task DoWorkAsync(PeriodicBackgroundWorkerContext workerContext) |
|||
{ |
|||
var newEventNotifier = workerContext.ServiceProvider.GetRequiredService<NewEventNotifier>(); |
|||
var eventRepository = workerContext.ServiceProvider.GetRequiredService<IRepository<Event, Guid>>(); |
|||
var asyncExecuter = workerContext.ServiceProvider.GetRequiredService<IAsyncQueryableExecuter>(); |
|||
|
|||
var eventQueryable = await eventRepository.GetQueryableAsync(); |
|||
|
|||
var eventQuery = eventQueryable.Where(x => x.IsEmailSentToMembers == false); |
|||
|
|||
var newEvents = await asyncExecuter.ToListAsync(eventQuery); |
|||
|
|||
foreach (var @event in newEvents) |
|||
{ |
|||
try |
|||
{ |
|||
await newEventNotifier.NotifyAsync(@event); |
|||
@event.IsEmailSentToMembers = true; |
|||
} |
|||
catch (Exception e) |
|||
{ |
|||
@event.IsEmailSentToMembers = false; |
|||
Logger.LogError($"An error occurred while sending an email to the members of the organization after the new event was created. Error message: {e.Message}"); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,77 @@ |
|||
using System; |
|||
using System.Linq; |
|||
using System.Threading.Tasks; |
|||
using EventHub.Emailing; |
|||
using EventHub.Organizations.Memberships; |
|||
using EventHub.Users; |
|||
using Volo.Abp.DependencyInjection; |
|||
using Volo.Abp.Domain.Repositories; |
|||
using Volo.Abp.Emailing; |
|||
using Volo.Abp.Linq; |
|||
using Volo.Abp.TextTemplating; |
|||
|
|||
namespace EventHub.Events |
|||
{ |
|||
public class NewEventNotifier : ITransientDependency |
|||
{ |
|||
private readonly IEmailSender _emailSender; |
|||
private readonly ITemplateRenderer _templateRenderer; |
|||
private readonly IRepository<OrganizationMembership, Guid> _organizationMembershipsRepository; |
|||
private readonly IRepository<AppUser, Guid> _userRepository; |
|||
private readonly IAsyncQueryableExecuter _asyncExecuter; |
|||
|
|||
public NewEventNotifier( |
|||
IEmailSender emailSender, |
|||
ITemplateRenderer templateRenderer, |
|||
IRepository<OrganizationMembership, Guid> organizationMembershipsRepository, |
|||
IRepository<AppUser, Guid> userRepository, |
|||
IAsyncQueryableExecuter asyncExecuter) |
|||
{ |
|||
_emailSender = emailSender; |
|||
_templateRenderer = templateRenderer; |
|||
_organizationMembershipsRepository = organizationMembershipsRepository; |
|||
_userRepository = userRepository; |
|||
_asyncExecuter = asyncExecuter; |
|||
} |
|||
|
|||
public async Task NotifyAsync(Event @event) |
|||
{ |
|||
if (@event is null) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
var organizationMembershipsQueryable = await _organizationMembershipsRepository.GetQueryableAsync(); |
|||
|
|||
var membershipQuery = organizationMembershipsQueryable |
|||
.Where(x => x.OrganizationId == @event.OrganizationId); |
|||
|
|||
var organizationMembers = await _asyncExecuter.ToListAsync(membershipQuery); |
|||
|
|||
foreach (var member in organizationMembers) |
|||
{ |
|||
var user = await _userRepository.FindAsync(member.UserId); |
|||
|
|||
if (user is null) |
|||
{ |
|||
continue; |
|||
} |
|||
|
|||
var model = new |
|||
{ |
|||
UserName = user.GetFullNameOrUsername(), |
|||
Title = @event.Title, |
|||
StartTime = @event.StartTime, |
|||
EndTime = @event.EndTime, |
|||
Url = @event.Url |
|||
}; |
|||
|
|||
await _emailSender.QueueAsync( |
|||
user.Email, |
|||
$"Do you attend the {@event.Title} event?", |
|||
await _templateRenderer.RenderAsync(EmailTemplates.NewEventCreated, model) |
|||
); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,47 @@ |
|||
using System.Threading.Tasks; |
|||
using EventHub.Emailing; |
|||
using EventHub.Users; |
|||
using Volo.Abp.DependencyInjection; |
|||
using Volo.Abp.Emailing; |
|||
using Volo.Abp.TextTemplating; |
|||
|
|||
namespace EventHub.Events.Registrations |
|||
{ |
|||
public class EventRegistrationNotifier : ITransientDependency |
|||
{ |
|||
private readonly IEmailSender _emailSender; |
|||
private readonly ITemplateRenderer _templateRenderer; |
|||
|
|||
public EventRegistrationNotifier( |
|||
IEmailSender emailSender, |
|||
ITemplateRenderer templateRenderer) |
|||
{ |
|||
_emailSender = emailSender; |
|||
_templateRenderer = templateRenderer; |
|||
} |
|||
|
|||
public async Task NotifyAsync( |
|||
Event @event, |
|||
AppUser user) |
|||
{ |
|||
if (user is null || @event is null) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
var model = new |
|||
{ |
|||
Title = @event.Title, |
|||
StartTime = @event.StartTime, |
|||
EndTime = @event.EndTime, |
|||
Url = @event.Url |
|||
}; |
|||
|
|||
await _emailSender.QueueAsync( |
|||
user.Email, |
|||
"Your event registration has been received!", |
|||
await _templateRenderer.RenderAsync(EmailTemplates.EventRegistration, model) |
|||
); |
|||
} |
|||
} |
|||
} |
|||
File diff suppressed because it is too large
@ -0,0 +1,24 @@ |
|||
using Microsoft.EntityFrameworkCore.Migrations; |
|||
|
|||
namespace EventHub.Migrations |
|||
{ |
|||
public partial class Added_IsRemindingEmailSent_To_Event : Migration |
|||
{ |
|||
protected override void Up(MigrationBuilder migrationBuilder) |
|||
{ |
|||
migrationBuilder.AddColumn<bool>( |
|||
name: "IsRemindingEmailSent", |
|||
table: "AppEvents", |
|||
type: "bit", |
|||
nullable: false, |
|||
defaultValue: false); |
|||
} |
|||
|
|||
protected override void Down(MigrationBuilder migrationBuilder) |
|||
{ |
|||
migrationBuilder.DropColumn( |
|||
name: "IsRemindingEmailSent", |
|||
table: "AppEvents"); |
|||
} |
|||
} |
|||
} |
|||
File diff suppressed because it is too large
@ -0,0 +1,24 @@ |
|||
using Microsoft.EntityFrameworkCore.Migrations; |
|||
|
|||
namespace EventHub.Migrations |
|||
{ |
|||
public partial class Added_IsEmailSentToMembers_To_Event : Migration |
|||
{ |
|||
protected override void Up(MigrationBuilder migrationBuilder) |
|||
{ |
|||
migrationBuilder.AddColumn<bool>( |
|||
name: "IsEmailSentToMembers", |
|||
table: "AppEvents", |
|||
type: "bit", |
|||
nullable: false, |
|||
defaultValue: false); |
|||
} |
|||
|
|||
protected override void Down(MigrationBuilder migrationBuilder) |
|||
{ |
|||
migrationBuilder.DropColumn( |
|||
name: "IsEmailSentToMembers", |
|||
table: "AppEvents"); |
|||
} |
|||
} |
|||
} |
|||
Loading…
Reference in new issue