Rendering HTML emails with inline CSS using Jinja - html-email

As you know, if you are going to send an HTML email, all CSS styling must be inline on the elements themselves e.g. <p style='font-family: Helvetica'>
Is there a way I can use Jinja to easily create HTML email bodies from Jinja templates without repeating CSS styles many times in a single template?
I think of setting these styles to variables e.g.
{% set FONT_STYLE = 'font-family: Helvetica; color: #111' %}
and then in the template I can do
<p style='{{ FONT_STYLE }}'>My paragraph here.</p>
Any better ideas? Maybe a library that resolves CSS rules that takes HTML content and CSS file and binds calculated CSS rules to the HTML elements one by one?

Look at premailer which turns CSS blocks into style attributes. You can get pretty html and convert it to email html with premailer.

Related

tinymce <span> gets removed when containing <br />

I'm using Tiny 4.9.10 to dynamically generate reports based on templates. Users can create templates which contain placeholders. These placeholders then get swapped out for their actual values when generating the actual report. The placeholders get their style (including font, which is the main issue here) from their enclosing <span>-tag.
When replacing the placeholder with their actual value, we use <br />-tags to insert new lines, since some of the placeholders are almost full reports on their own which need to be structured.
After the placeholders have all been replaced, we inject this dynamically generated content back into a Tiny editor, so as to allow users to make ad hoc changes to the content.
At this point however we noticed that the <span>-tag around a piece of generated content containing <br />-tags gets removed. This is a problem, because the style info that was enclosed in this tag gets removed as well, resulting in problems further down the line when generating a PDF.
What I've tried to work around this:
setting verify_html to false
adding +span[br]/+span[br /] to valid_children
setting forced_root_bloc to div
The first two options did nothing to help me, and while the last one looked promising, it didn't help, because even when using <div>, font info gets enclosed into a child <span>.
I know this is expected behavior, because <span> is an inline tag and so it shouldn't have <br /> tags as children, but I'm currently at a loss for a workaround which allows me to include <br /> tags into my dynamically generated content without losing the style (most importantly the font) of the parent tag.
So I solved this by replacing the <span> tags by <div> tags when we swap out the placeholders by using some regex looking for spans that enclose a <p>...<\p> or a <b />. This stops Tiny from throwing away the <span> tags when they contain either of these enclosed tags
TinyMCE considers the <span> <br /> </span> construct an empty space and deletes it in favor of optimization.
I may be late, but you can also try using this callback in the setup option to stop the editor from removing empty spans:
setup: function(editor) {
editor.on('PreInit', function() {
editor.schema.getElementRule('span').removeEmpty = false;
});
}

Does SendGrid template engine have conditionals?

Sending transactional apis through SendGrid. My template (ported over from Mailchimp) has conditionals (e.g.
*|IF:SHOWTHISSECTION|*
in Mailchimp syntax). This includes or excludes sections of the template based on a variable.
I can't find the analog in SendGrid, does it simply not have this capability? I'd like to suppress certain sections depending on the presence/absence of a substitution variable.
SendGrid supports this natively now:
{{#if user.profile.male}}
<p>Dear Sir</p>
{{else if user.profile.female}}
<p>Dear Madame</p>
{{else}}
<p> Dear Customer</p>
{{/if}}
Reference: https://sendgrid.com/docs/for-developers/sending-email/using-handlebars/#conditional-statements
It's a horrible hack, but by introducing new variables and using CSS, you can hide the relevant portions of mails using display. So where before in Mandrill/MailChimp I'd have something like:
*|IF:FAKEVAR|*
<p>Show some text here</p>
*|END:IF|*
Instead, introduce a new variable IF_FAKEVAR, whose value is either "none" or "inherit" depending on whether FAKEVAR has a value, then do this:
<p style="display: *|IF_FAKEVAR|*">Show some text here</p>
While it's a hack, for very complex email templates, it avoids sending 70k bytes to the server for every single email, which when you have thousands or tens of thousands of mails, is prohibitive.
SendGrid templating does not support this, but you can use a templating API like sendwithus to accomplish this on top of your SendGrid account. I believe sendwithus supports jinja conditionals, so you could do the following:
{% if variable %}
<h1>{{ variable }}</h1>
{% endif %}
Sendgrid supports conditional using Handlebar
{{#if user.profile.male}}
<p>Dear Sir</p>
{{else if user.profile.female}}
<p>Dear Madame</p>
{{else}}
<p> Dear Customer</p>
{{/if}}
from their documentation here https://sendgrid.com/docs/for-developers/sending-email/using-handlebars/#conditional-statements
Below handlebars can be used in Sendgrid dynamic templates:
Conditional statements:
{{#if variable}}
{{#unless variable}}
{{#greaterThan variable value}}
{{#lessThan variable value}}
{{#equals variable value}}
{{#notEquals variable value}}
{{#and variable1 variable2}}
{{#or variable1 variable2}}
Looping statements:
{{#each hash}}
Refer https://sendgrid.com/docs/for-developers/sending-email/using-handlebars/ for detailed information
SendGrid doesn't have true conditionals, but it does have Section Tags. With those, you can define a block of text at the message level (as opposed to the distinct recipient level of a Substitution Tag), and then call the appropriate section for the recipient as needed.
I Know this is old, but I had the same problem and I found a solution compatible with several email managers that maybe it's helpful for someone.
You can use substitution tags with the html comment symbols value in case you want to hide a section.
{%OPEN_COMMENT}
<h1>Whatever section you want to hide</h1>
{%CLOSE_COMMENT}
Replace tags with "" respectively if you want to hide the section. Replace them with empty strings in the other case.

TypoScript: select a specific content element from a column

What is the best way to select a single content element?
I have a static html template like this:
<html>
...
<div class="left clearfix">
<h1><img src="fileadmin/templates/images/ueberschrift_startseite.png" alt="Willkommen" /><span>Willkommen</span></h1>
<p>EINLEITUNGSTEXT 1 EINLEITUNGSTEXT 1</p>
<ul>
<li>LI 1</li>
<li>LI 2</li>
<li>LI 3</li>
<li>LI 4</li>
</ul>
<h3>HEADLINETEXT 3</h3>
<p>TEXT TEXT TEXT TEXT </p>
</div>
...
</html>
In my Backend I have added
A Content Element for the <h1>
A Content Element that should be displayed between the <p> Tags where now Einleitungstext1 is displayed
A Content Element that contains the LI for the UL Section
and so on.
All Elements are in the same column.
I what to take my static HTML Template and fill several SPECIFIC parts with elements that can be edited in the backend.
I hope I could explain what my problem is.
How do you configure your templates? Is there a much better way to replace only specific parts of a static template?
Regards,
Max
I assume that you know how to use marks and subparts in TypoScript, in such case what you have to do is set marks in your template, put each CE in separate column (maybe you'll need to add custom columns if all left, default, right and border (0-3) columns are used for other things) and finally just map these columns to the marks.
tip: TemplaVoila allows for more combinations as you can map not only container for CE's but also other things (header fields, image fields, TS snippets etc.)

MVC 2 EditorForModel specify width of generated input

I use the Html.EditorForModel() in a view to generate fields for the edit form. I also have another partial class where I specify some Data Annotation attributes for some fields (like DisplayName, Range etc).
When I run the application I have HTML inputs generated for each field. How can I specify the width of this generated inputs ?
Something like this:
<input id="nameTextBox" style="width:220px" name="theName" />
#Gerrie's solution works, but it applies to all inputs on the page. If you have other inputs on the page that you don't want to style this way, then you can do something like this:
<div id="model-editor">
<%: Html.EditorForModel() %>
</div>
And then use CSS of this form:
#model-editor input { width:220px; }
EDIT
If you want to set CSS rules for individual fields, you can do so too. Inspect the generated HTML and find the input's id, then do:
input[id='YourInputId'] { width:400px; }
use CSS:
input
{
width: 220px;
}
This way you don't have to bother about inserting these style attributes into the generated controls.

Disabling data detectors for a specific HTML element in a UIWebView

Does anyone know if it's possible to disable the data detectors for phone numbers, email addresses etc in a UIWebView, for specific HTML elements only?
I'd like the detectors to be active for most of the content loaded into the UIWebView, but disable it in certain areas.
If this is possible, I'm assuming it would be achieved by using an HTML attribute in the loaded content (rather than setting some sort of UIWebView property), e.g.
<html>
<body>
<h1 datadetectors="off">Header text with number 9123 3456</h1>
<p>Body text with number 9872 4567</p>
</body>
</html>
In this example, the number in the <p> would be detected as a phone number due to setting webview.dataDetectorTypes = UIDataDetectorTypeAll, whereas the number in the <h1> would not.
you should use <meta name = "format-detection" content = "telephone=no">
Hope it helps
you can put the attribute
x-apple-data-detectors="false"
but unfortunately this seems to work only for tags.
I ended up using this solution:
666-777-777
besides disabling the telephone numbers "detection", this also prevents adresses and other detection to run.
If you control the web content you can use jscript (via jquery) to write your own data detectors. If you don't control the content you could insert and execute the jscript using stringByEvaluatingJavaScriptFromString: once webViewDidFinishLoad: is called.
In WKWebView Disable all Data Detector Types in Attributes inspector. This will solve your problem
Since an "a" tag will be inserted for you with the x-apple-data-detectors in it, you could write the tag yourself with x-apple-data-detectors set to false.
Original code:
<div class="my_time">17:02</div>
will be transformed to:
<div class="my_time">
<a href="x-apple-data-detectors://1" dir="ltr"
x-apple-data-detectors="true"
x-apple-data-detectors-type="calendar-event"
x-apple-data-detectors-result="1"
style="color: rgb(169, 169, 169);
text-decoration-color: rgba(169, 169, 169, 0.258824);">14:18
</a>
</div>
You can prevent this by writing your code as following...
<div class="my_time">
<a x-apple-data-detectors="false" style="text-decoration: none">17:02</a>
</div>