Coder Social home page Coder Social logo

doxakis / mailbody Goto Github PK

View Code? Open in Web Editor NEW
158.0 10.0 13.0 193 KB

Create transactional email with a fluent interface (.net)

Home Page: https://doxakis.github.io/MailBody/

License: MIT License

C# 41.98% HTML 58.02%
dotnetcore fluent-interface csharp dotnet email

mailbody's People

Contributors

doxakis avatar jjavierdguezas avatar ramon-balaguer avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

mailbody's Issues

m.IsProperty() is always false

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.

image

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

image


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.

Pass attributes to Paragraph with Block content

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:

public MailBlockFluent Paragraph(MailBlockFluent block, dynamic attributes = null)
{
_commands.Add(() =>
{
// Propagate template.
block._template = this._template;
var element = new ContentElement
{
Content = block.ToString()
};
return _template.Paragraph()(element);
});
return this;
}

should MailBody pass the attributes argument to the ContentElement ?

PS: I can submit the PR if needed

Line breaks are not showing in Gmail

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):
image

the generated html (on gmail) doesnt even have the line breaks

image

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">&nbsp;</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">&nbsp;</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:

outlook:
image

thunderbird:
image

roundcube:
image


I checked and Mailbody uses </br> as the line break html tag by default:

.LineBreak(m => $"</br>")

Is there a reason for that? Changing it to <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(); 

gmail
image

New logo for MailBody

I wanted to contribute to Mail Body. I designed a logo for MailBody. If you like it, I'll send you the files.

mailbody
bodymail

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.