doxakis / mailbody Goto Github PK
View Code? Open in Web Editor NEWCreate transactional email with a fluent interface (.net)
Home Page: https://doxakis.github.io/MailBody/
License: MIT License
Create transactional email with a fluent interface (.net)
Home Page: https://doxakis.github.io/MailBody/
License: MIT License
I am creating this issue for future reference in case someone else encounters the same problem I had while using MailBody
.
Scenario: I extended the default MailBody
template in a different library from where I was using it. In addition to modifying the HTML of the template, I also allowed passing CSS attributes through the dynamic attributes
parameter of MailBody
.
|-- MyProj
|-- MyProj.Shared.Services.csproj
|-- Email
|-- Brand
|-- MailBodyExtensions.cs
|-- MyProj.App.csproj
|-- Program.cs
// MyProj.Shared.Services library
namespace MyProj.Shared.Services.Email.Brand
{
public static class MailBodyExtensions
{
public static MailBlockFluent GetTemplate()
{
var template = MailBodyTemplate.GetDefaultTemplate();
// ...
template.Link(m =>
{
var withColorStyles = m.IsProperty(() => m.Attributes.color);
var withBackgroundColorStyles = m.IsProperty(() => m.Attributes.backgroundColor);
var withFontWeightStyles = m.IsProperty(() => m.Attributes.fontWeight);
var withFontSizeStyles = m.IsProperty(() => m.Attributes.fontSize);
var withMarginBottomStyles = m.IsProperty(() => m.Attributes.marginBottom);
return $"<a href='{m.Link}' style='line-break: anywhere;" +
(withColorStyles ? $"color:{m.Attributes.color};" : string.Empty) +
(withBackgroundColorStyles ? $"background-color:{m.Attributes.backgroundColor};" : string.Empty) +
(withFontWeightStyles ? $"font-weight:{m.Attributes.fontWeight};" : string.Empty) +
(withFontSizeStyles ? $"font-size:{m.Attributes.fontSize};" : string.Empty) +
(withMarginBottomStyles ? $"Margin-bottom:{m.Attributes.marginBottom};" : string.Empty) +
$"'>{m.Content}</a>";
});
// ...
return template;
}
}
}
// MyProj.App > Program.cs
using MyProj.Shared.Services.Email.Brand;
namespace MyProj.App
{
public class Program
{
public static async Task Main()
{
// ...
var body = MailBodyExtensions
.GetTemplate()
// ...
.Link(callbackUrl, callbackUrl, new { color = "#7F88A1", fontSize = "12px" });
await _emailService.SendEmailAsync(/*...*/, body, /*...*/);
// ...
}
}
}
Problem: However, I encountered a problem where m.IsProperty(() => m.Attributes.prop)
always returned false
, even though I passed the argument correctly and could see that the object had the field while debugging.
I spent a considerable amount of time resolving this issue. If someone else encounters the same problem, I can share the solution I found. While researching the issue, I came across two relevant questions on Stack Overflow: Q 8465121 and Q 19936397.
Explanation: Anonymous objects are internal
, which means their members are very restricted outside of the assembly that declares them. dynamic
respects accessibility, so pretends not to be able to see those members. If the call was in the same assembly, it would work.
Solution 1: The obvious one: move the MailBody
extension code to the same assembly/library
Solution 2: Use InternalsVisibleTo
to expose internal
values to other lib
// MyProj.App.csproj
<ItemGroup>
<InternalsVisibleTo Include="MyProj.Shared.Services" />
</ItemGroup>
And it works like a charm
This issue can be closed without taking any further action. However, it may be helpful to include a comment about this in the README file.
Hi, first thanks for this awesome tool
--
This is my issue:
I have made changes to the Paragraph
template so that it can accept fontSize
and color
attributes, similar to the example provided in the README.md file):
template.Paragraph(m => $"<p style='font-family: sans-serif; font-size: {(m.IsProperty(() => m.Attributes.fontSize) ? m.Attributes.fontSize : "14px")}; font-weight: normal; margin: 0; Margin-bottom: 15px;{(m.IsProperty(() => m.Attributes.color) ? $" color: {m.Attributes.color};" : string.Empty)}'>{m.Content}</p>");
Then I have a paragraph with a Block inside
var body = MailBody
.CreateBody()
....
.Paragraph(MailBody.CreateBlock().Text("Text...").LineBreak().Link(url), new { color = "#7F88A1", fontSize = "12px" });
but Attributes
is null
in Paragraph
func
Reviewing MailBody
codebase I found this:
MailBody/src/MailBody/MailBlockFluent.cs
Lines 86 to 100 in 730abf4
should MailBody
pass the attributes
argument to the ContentElement
?
PS: I can submit the PR if needed
when using MailBody
's .LineBreak()
I expected a new line to be rendered. It does on all mailboxes I tested except for gmail, even doing .LineBreak().LineBreak()
doesnt work.
example:
var html = MailBody
.CreateBody()
.Paragraph(
MailBody.CreateBlock()
.Text("Line 1")
.LineBreak()
.Text("Line 2")
).ToString();
is rendered on gmail like (even on mobile):
the generated html (on gmail) doesnt even have the line breaks
this this the html rendered on gmail:
<div style="font-family:sans-serif;font-size:14px;line-height:1.4;background-color:#f6f6f6;margin:0;padding:0">
<table border="0" cellpadding="0" cellspacing="0" style="border-collapse:separate;width:100%;background-color:#f6f6f6" width="100%" bgcolor="#f6f6f6">
<tbody><tr>
<td style="font-family:sans-serif;font-size:14px;vertical-align:top" valign="top"> </td>
<td style="font-family:sans-serif;font-size:14px;vertical-align:top;display:block;Margin:0 auto!important;max-width:580px;padding:10px;width:580px" width="580" valign="top">
<div style="box-sizing:border-box;display:block;Margin:0 auto;max-width:580px;padding:10px">
<table style="border-collapse:separate;width:100%;background:#fff;border-radius:3px" width="100%">
<tbody><tr>
<td style="font-family:sans-serif;font-size:14px;vertical-align:top;box-sizing:border-box;padding:20px" valign="top">
<table border="0" cellpadding="0" cellspacing="0" style="border-collapse:separate;width:100%" width="100%">
<tbody><tr>
<td style="font-family:sans-serif;font-size:14px;vertical-align:top" valign="top">
<p style="font-family:sans-serif;font-size:14px;font-weight:normal;margin:0;Margin-bottom:15px">Line 1Line 2</p>
</td>
</tr>
</tbody></table>
</td>
</tr>
</tbody></table>
<div style="clear:both;padding-top:10px;text-align:center;width:100%">
<table border="0" cellpadding="0" cellspacing="0" style="border-collapse:separate;width:100%" width="100%">
<tbody><tr>
<td style="font-family:sans-serif;vertical-align:top;padding-top:10px;padding-bottom:10px;font-size:12px;color:#999999;text-align:center" valign="top" align="center">
<span class="m_2679512226725185239apple-link" style="color:#999999;font-size:12px;text-align:center"></span>
</td>
</tr>
</tbody></table>
</div>
</div>
</td>
<td style="font-family:sans-serif;font-size:14px;vertical-align:top" valign="top"> </td>
</tr>
</tbody></table>
<img src="https://ci3.googleusercontent.com/meips/ADKq_NY-uHKHVIUA45slAlsfFp41esqM4U87Mm4Ph16VBOJ11Cz5jhEx6YKd3QOQuveRY3rlkL3oZzvv2Ex1RgovDhk5yAPX0qkRnJj4ZLOMETWRapWpXpGXVyy4QMBgH-fbNIK3MqSF7iXqln9pWLMXfBJQk12hHF_mro2Uu5supG5U64neA_HAVznsCjvmuOHcvJ3Kx87oVz1q-uynMApMzf78w6UxKRyGOUhc3hsxF_O1c1YY-8n4FyE2raj1zyfE-5eDBVknAtmsPyCQgtYrnDp9toaEBF28rWfh7Ws1dJIZZ54lm3bFvewXwk6bcR3StygiEUS_LebtqVjzHk5xtbS3yhrV67vMwC_mBU5cmYUFu0fnF2qnT_AS8bvFGPl2X_yASX_l_20kZ90W-JgtfXtWRVIj3x2AEoHunMQjKw94=s0-d-e1-ft#https://u44648080.ct.sendgrid.net/wf/open?upn=u001.KWZj6qljYBLPISGik8oOPR-2FDzMnz3tV-2BdvyMDmVmQiu9GoKoBpbEoUzPMH6FYwchfP87LAcBwG6q4Aw5C-2BfFzMmHF8jEU1UXex65ENFrztxg5Mul5rwNqmkKrvHj7YNwmggd13EH9mOlpWkUsgrug6WYjf2aTT8XXxy9ku3kUJyPq5rENlQPBhiX6cfp5Kd6K-2FRXLP2bfbZI2bVs54kWsJ8NgTujyMiDk3GZKMR5l5o-3D" alt="" width="1" height="1" border="0" style="height:1px!important;width:1px!important;border-width:0!important;margin-top:0!important;margin-bottom:0!important;margin-right:0!important;margin-left:0!important;padding-top:0!important;padding-bottom:0!important;padding-right:0!important;padding-left:0!important" class="CToWUd" data-bit="iit"></div>
It seems that it is a Gmail only issue:
I checked and Mailbody
uses </br>
as the line break html tag by default:
MailBody/src/MailBody/MailBodyTemplate.cs
Line 140 in fcd58da
<br>
as it appears on W3Schools (https://www.w3schools.com/tags/tag_br.asp) seems to work.
var template = MailBodyTemplate.GetDefaultTemplate().LineBreak(x => "<br>");
var html = MailBody
.CreateBody(template)
.Paragraph(
MailBody.CreateBlock()
.Text("Line 1")
.LineBreak()
.Text("Line 2")
).ToString();
Hi,
After review the examples I found that this one is not working https://rawgit.com/doxakis/MailBody/master/src/Example/Output/Withfooter.html
May be it's bug in test...?
It'll be great if you add Header as text or/and a logo image is presented in here
https://htmlemail.io/img/preview-password.jpg
Any way you this template is in use.
THANKS !!!
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.