How to insert dynamic blocks of html inside SendGrid email? - html

I'm using SendGrid web API v3. Trying to generate personalization object which includes many recipients. Each recipient has 1 email with data that related to current recipient (pass with substitutions)
Example:
personalizations: [{
to: [{email: 'example#mail.com'}],
subject: 'Hello, :name!',
substitutions: {':name': 'John', ':info_section_html':'<p>Some useful block1</p><p>Some useful block2</p>'}
},
{
to: [{email: 'example#mail.com'}],
subject: 'Hello, :name!',
substitutions: {':name': 'John', ':info_section_html':'<p>Some useful block1</p><p>Some useful block2</p><p>Some useful block3</p><p>Some useful block4</p><p>Some useful block5</p><p>Some useful block6</p>'}
}
],
from: {email: 'send#example.com'},
content: [{type: 'text/html', value: 'Hello, :name! </br> Here are your very usefull info</br> :info_section_html'}]
When substitution: info_section_html has a lot of such blocks it crossed a limit of 10000 bytes. My blocks have a lot more HTML than in example. Each recipient can have a different number of blocks that's why I can't include them in content attribute.
Also was thinking about sections attribute where I can pass HTML of my info_section_html. But can't pass array of data in substitution.
Can someone please suggest how to overcome this?

I know this comes quite late, but I was facing the same issue and couldn't find the answer so I'd figured that maybe it would be useful to still post it here:
As can be found here: SendGrid API v3
A collection of key/value pairs following the pattern "substitution_tag":"value to substitute". All are assumed to be strings. These substitutions will apply to the text and html content of the body of your email, in addition to the subject and reply-to parameters. The total collective size of your substitutions may not exceed 10,000 bytes per personalization object.
So there's nothing to do about it here.
For this usage Sendgrid has another feature called Sections (check link above as well). They work almost like Substitutions except that they're are link to the whole mail and not per Substitution
They can be used together with Substitutions to achieve behavior like stated above.
As said by mbernier here: Github issue related to the topic
You can use them like this:
"personalizations: [
{
"to: [{"email":"bob#example.com"}],
"substitutions": {
"[%product_info%]": "[%has_product%]",
},
},
{
"to":[{"email":"bob#example.com"}],
"substitutions": {
"[%product_info%]": "[%no_product%]",
},
}],
"content": [
{
"type": "text/plain",
"value": "We just wanted to tell you that we appreciate you being a long time customer! [%product info%]"
}],
"sections": {
"[%has_product%]": "Also, thanks for ordering:<br />[%product_section%].<br /> Are you ready to order again!?",
"[%no_product%]": "You haven't ordered in a while, but we'd love it if you came back and saw our new products!"
}
Most important here is that the sections should be added via a substitution tag.
Hope this helps

Related

Using FeedIron to remove links from TT-RSS feeds

I'm trying to come up with a formula to remove all links from a feed's content. I'm using FeedIron on TT-Rss.
This is what I've got so far:
{
"url": "example.com",
"type": "regex",
"pattern": "^(http:\/\/www\.|https:\/\/www\.|http:\/\/|https:\/\/)?[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,5}(:[0-9]{1,5})?(\/.*)?$",
"replace": " "
}
I'm guessing that's already wrong(it's throwing an "Invalid JSON" error), but then again I'm not specialized at all. I just want to be able to receive the feeds without random links in the article content. Be it media links or any kind of link.
Can someone please help me? Thank you!
Maintainer of Feediron here.
Feediron doesn't work on the Article stub that comes in the RSS feed. It fetches the page source and then you modify the returned data.
The reason it's throwing a Invalid JSON error is because you have to escape the special characters in your regex.
E.G. using the website: https://www.freeformatter.com/json-escape.html
^(http:\/\/www\.|https:\/\/www\.|http:\/\/|https:\/\/)?[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,5}(:[0-9]{1,5})?(\/.*)?$
Becomes:
^(http:\\\/\\\/www\\.|https:\\\/\\\/www\\.|http:\\\/\\\/|https:\\\/\\\/)?[a-z0-9]+([\\-\\.]{1}[a-z0-9]+)*\\.[a-z]{2,5}(:[0-9]{1,5})?(\\\/.*)?$
Also your configuration is not a correct format the example regex config:
"example.tld":{
"type":"xpath",
"xpath":"article",
"reformat": [
{
"type": "regex",
"pattern": "^(http:\\\/\\\/www\\.|https:\\\/\\\/www\\.|http:\\\/\\\/|https:\\\/\\\/)?[a-z0-9]+([\\-\\.]{1}[a-z0-9]+)*\\.[a-z]{2,5}(:[0-9]{1,5})?(\\\/.*)?$",
"replace": " "
}
]
}
Also note in the Testing tab you need to drop the domain "example.tld": for it to work

Can I set a simple key-value pair using amp-state?

I am trying to set a simple {key: value} pair using amp-state. Currently in my code there I have to initialize on every set state for key - value pairs.
The project is using express-handlebar templates and AMP for state management in the templates. There is a default handlebar value for each key.
But when one value is changed I have to initialize all the amp state values. This leads to a lot of duplicate code that could be improved a lot by setting state an initial. But to refactor all amp state into a big object containing the key-value pairs will complicate my code quite a bit so i'd rather not use the exact examples you can find on amp documentation.
For example I would like to replace something like this:
tap:AMP.setState({
lng: 'en',
selectedVal: selectedVal || '{{baseVal}}',
rate: rate || {{lookup currencyRates baseCurrency}},
symbol: symbol || '{{lookup symbols baseCurrency}}'
}),
with
tap:AMP.setState({
lng: 'en',
}),
In order to do this (and avoid errors) I would need to initialize all fields at the bottom of the page using <amp-state>...</amp-state> (and only changing the language in this case)
I tried to search for a solution, but I was not able. Does anyone know if there is a solution? If yes witch? If not, does anyone knows why?
Thanks in advice.
AMP.setState allows you to deep merge state objects:
https://amp.dev/documentation/components/amp-bind/?format=websites#deep-merge-with-amp.setstate()
I think you're missing initialisation of a state object which will allow you to populate state with your default values.
https://amp.dev/documentation/components/amp-bind/?format=websites#initializing-state-with-amp-state
You can do this either by a) rendering JSON directly into an amp-state component or b) by using the src
attribute to retrieve data from an endpoint.
a) Server-rendered state
<amp-state id="myStateObject">
<script type="application/json">
{
"lng": "en",
"selectedVal": "lookup baseVal",
"rate": "lookup currencyRates baseCurrency",
"symbol": "lookup symbols baseCurrency"
}
</script>
</amp-state>
OR
b) Using the src attribute
<amp-state id="myStateObject" src="/some/json/endpoint"></amp-state>
This gives you access to myStateObject which you can then use to merge an object literal with your current state.
<button
on="tap:AMP.setState({
myStateObject: {
selectedVal: 'newSelectedVal'
}
})"
>
Click me
</button>
I finally found my answer. Maybe it will help others too.
So even tough in the amp bind documentation there are no examples with just a key-value pair, seems like on this page there is.
The conclusion is you can load a simple key-value pair by just inserting a simple string inside the script tag (similar to this example they have on the second page):
<amp-state id="myText">
<script type="application/json">
"World"
</script>
</amp-state>
I found it quite confusing because I was expecting that inside the script tag you should place a json object. But this seems to work just fine.

How would you embed atomic partials into a template data object

I'm using handlebars and assemble with yeoman and gulp.
I want to have some globalized partials that are able to be nested or injected into another partial by calling it within the context of a data object.
A simple example of that would be having a list of links that I could reference inside content throughout the site. The reason behind this, is the need for consistency. If for example, if I have a link within text on a page that I reference a 15 times throughout an entire website, but then realize I need to add a trade mark or modify the text, I want to update it once, not 15 times.
This is an example of what I want to do. Define global data inside a json file:
links.json
{
"apple": {
"linktext": "apple",
"target": "_blank",
"href": "http://www.apple.com"
},
"blog-article-foo-bar": {
"linktext": "foo bar",
"href": "http://www.foobar.com"
},
"dell": {
"linktext": "dell",
"target": "_parent",
"href": "http://www.dell.com"
}
}
Generate a partial from that content using a simple or complex template:
links.hbs
<a href="{{href}}" {{#if target}}target="{{target}}"{{/target}}>{{linktext}}</a>
And be able to embed that partial into another one by referencing it some how. This didn't work, but I've been reading about custom helpers, but can't figure out how I would intercept the partial and bind it into the other partial.
text.json
{
"text": "If you need a computer, go to {{> link link.apple}}."
}
text.hbs
<p>
{{text}}
</p>
compiled.html
<p>
If you need a computer, go to apple.
</p>
If you have suggestions or examples that might help me understand how to achieve this, I'd really appreciate the support. Thanks in advance.
There is some information about Handlebars helpers in their docs but not that much.
Since you're trying to use handlebars syntax in the value of a property on the context (e.g. text), handlebars won't render the value since it's already rendering the template. You can create your own helper that can render the value like this:
Handlebars.registerHelper('render', function(template, options) {
// first compile the template
const fn = Handlebars.compile(template);
// render the compiled template passing the current context (this) to
// ensure the same context is use
const str = fn(this);
// SafeString is used to allow HTML to be returned without escaping it
return new Handlebars.SafeString(str);
});
Then you would use the helper in your templates like this:
{{render text}}
Thanks for the example #doowb, your code did work but not for what I was trying to do. I really wanted something more complicated but I simplified my question not knowing it would be an issue. The code you provided worked (I think after a slight tweak) for a simple render of a template, but my templates use helpers such as #each and #if which caused the issue. Where the helpers were in my template, I ended up getting async placeholders. For example: <a $ASYNC$1$3...> I later learned this has to do with how partials are rendered. Understanding that lead me to subexpressions and the below solution.
Keeping my example above with some modifications, this is how I was able to merge partials.
First, I simplified the placeholder in text.json to basically a unique ID, instead of trying to render the partial there.
On the hbs template that I'm rendering to, such as a page or whatever, I included the insert helper with 3 arguments. The first two are subexpressions, each return a flattened partials as strings. The key here is that subexpressions process and return a result before finishing the current process with the helper. So two flattened templates are then sent to the helper along with the placeholder to search for.
The helper uses the third argument in a regex pattern. It searches the second argument (flattened parent template) for this pattern. When found, it replaces each instance of the pattern with the first argument (yes its a global fine replace).
So, the flattened child string gets inserted into parent each time placeholder is found.
First argument
(partial "link" link.apple)
Returns
'apple'
Second argument
(partial "text" text.text-example)
Returns
'<p class="text font--variant">If you need a computer, go to {{linkToApple}}.</p>'
Third argument
'linkToApple'
text.json
{
"text-example": {
"elm": "quote",
"classes": [
"text",
"font--variant"
],
"text": "If you need a computer, go to {{linkToApple}}."
}
}
text.hbs
<{{elm}} class="{{#eachIndex classes}}{{#isnt index 0}} {{/isnt}}{{item}}{{/eachIndex}}">{{text}}</{{elm}}>
compile.hbs
{{insert (partial "link" link.apple) (partial "text" text) 'linkToApple' }}
compile.html
<p class="text font--variant">If you need a computer, go to apple.</p>
gulpfile.js
app.helper('insert', function(child, parent, name) {
const merged = parent.replace(new RegExp('\{\{(?:\\s+)?(' + name + ')(?:\\s+)?\}\}', 'g'), child);
const html = new handlebars.SafeString(merged);
return html;
});
Hope this helps someone else. I know this can use improvements, I'll try to update it when I get back to cleaning up my gulp file.

Best practices for Storing JSON in DOM

I want to render some json data using HTML template.
I haven't started implementing anything yet, but I would like to be able to "set" values of data from json to html element which contains template for one record, or to render some collection of items using some argument which is template html for each item, but also to be able to get JSON object back in same format as source JSON which was used to render item (I want my initial JSON to contain some more information about behavior of record row, without the need to make ajax request to check if user can or can't do something with this record, and not all of this info is visible in template).
I know that I could make hidden form with an input element for each property of object to store, and mapper function to/from JSON, but it sounds like overkill to me, and I don't like that, I want some lighter "envelope".
I was wondering is there some JS library that can "serialize" and "deserialize" JSON objects into html so I can store it somewhere in DOM (i.e. in element which contains display for data, but I want to be able to store additional attributes which don't have to be shown as form elements)?
UPDATE As first answer suggested storing JSON in global variable, I also have thought about that, and my "best" mental solution was to make JavaScript module (or jQuery plugin) which would do "mapping" of JSON to html, and if not possible to store values in html then it can store them in internal variable, so when I want to "get" data from html element it can pull it from its local copy. I want to know is there better way for this? If there is some library that stores this info in variable, but does real-time "binding" of that data with html, I would be very happy with that.
UPDATE 2 This is now done using http://knockoutjs.com/, no need to keep json in DOM anymore, knockout does the JSON<=>HTML mapping automatically
Why not store it as nature intended: as a javascript object? The DOM is a horrible place.
That said, jQuery has the data method that allows just this.
So you want to keep a reference to the JSON data that created your DOMFragment from a template?
Let's say you have a template function that takes a template and data and returns a DOM node.
var node = template(tmpl, json);
node.dataset.origJson = json;
node.dataset.templateName = tmpl.name;
You can store the original json on the dataset of a node. You may need a dataset shim though.
There is also no way to "map" JSON to HTML without using a template engine. Even then you would have to store the template name in the json data (as meta data) and that feels ugly to me.
I have done this in the past as well in a couple of different ways.
The $('selector').data idea is probably one of the most useful techniques. I like this way of storing data because I can store the data in a logical, intuitive and orderly fashion.
Let's say you have an ajax call that retrieves 3 articles on page load. The articles may contain data relating to the headline, the date/time, the source etc. Let's further assume you want to show the headlines and when a headline is clicked you want to show the full article and its details.
To illustrate the concept a bit let's say we retrieve json looking something like:
{
articles: [
{
headline: 'headline 1 text',
article: 'article 1 text ...',
source: 'source of the article, where it came from',
date: 'date of the article'
},
{
headline: 'headline 2 text',
article: 'article 2 text ...',
source: 'source of the article, where it came from',
date: 'date of the article'
},
{
headline: 'headline 3 text',
article: 'article 3 text ...',
source: 'source of the article, where it came from',
date: 'date of the article'
}
]
}
From an ajax call like this . . .
$.ajax({
url: "news/getArticles",
data: { count: 3, filter: "popular" },
success: function(data){
// check for successful data call
if(data.success) {
// iterate the retrieved data
for(var i = 0; i < data.articles.length; i++) {
var article = data.articles[i];
// create the headline link with the text on the headline
var $headline = $('<a class="headline">' + article.headline + '</a>');
// assign the data for this article's headline to the `data` property
// of the new headline link
$headline.data.article = article;
// add a click event to the headline link
$headline.click(function() {
var article = $(this).data.article;
// do something with this article data
});
// add the headline to the page
$('#headlines').append($headline);
}
} else {
console.error('getHeadlines failed: ', data);
}
}
});
The idea being we can store associated data to a dom element and access/manipulate/delete that data at a later time when needed. This cuts down on possible additional data calls and effectively caches data to a specific dom element.
anytime after the headline link is added to the document the data can be accessed through a jquery selector. To access the article data for the first headline:
$('#headlines .headline:first()').data.article.headline
$('#headlines .headline:first()').data.article.article
$('#headlines .headline:first()').data.article.source
$('#headlines .headline:first()').data.article.date
Accessing your data through a selector and jquery object is sorta neat.
I don't think there are any libraries that store json in dom.
You could render the html using the data from json and keep a copy of that json variable as a global variable in javascript.

Effective method to hide email from spam bots [duplicate]

Closed. This question is opinion-based. It is not currently accepting answers.
Closed 1 year ago.
Locked. This question and its answers are locked because the question is off-topic but has historical significance. It is not currently accepting new answers or interactions.
When placing email addresses on a webpage do you place them as text like this:
joe.somebody#company.com
or use a clever trick to try and fool the email address harvester bots? For example:
HTML Escape Characters:
joe.somebody#company.com
Javascript Decrypter:
function XOR_Crypt(EmailAddress)
{
Result = new String();
for (var i = 0; i < EmailAddress.length; i++)
{
Result += String.fromCharCode(EmailAddress.charCodeAt(i) ^ 128);
}
document.write(Result);
}
XOR_Crypt("êïå®óïíåâïäùÀãïíðáîù®ãïí");
Human Decode:
joe.somebodyNOSPAM#company.com
joe.somebody AT company.com
What do you use or do you even bother?
Working with content and attr in CSS:
.cryptedmail:after {
content: attr(data-name) "#" attr(data-domain) "." attr(data-tld);
}
<a href="#" class="cryptedmail"
data-name="info"
data-domain="example"
data-tld="org"
onclick="window.location.href = 'mailto:' + this.dataset.name + '#' + this.dataset.domain + '.' + this.dataset.tld; return false;"></a>
When javascript is disabled, just the click event will not work, email is still displayed.
Another interesting approach (at least without a click event) would be to make use of the right-to-left mark to override the writing direction. more about this: https://en.wikipedia.org/wiki/Right-to-left_mark
This is the method I used, with a server-side include, e.g. <!--#include file="emailObfuscator.include" --> where emailObfuscator.include contains the following:
<!-- // http://lists.evolt.org/archive/Week-of-Mon-20040202/154813.html -->
<script type="text/javascript">
function gen_mail_to_link(lhs,rhs,subject) {
document.write("<a href=\"mailto");
document.write(":" + lhs + "#");
document.write(rhs + "?subject=" + subject + "\">" + lhs + "#" + rhs + "<\/a>");
}
</script>
To include an address, I use JavaScript:
<script type="text/javascript">
gen_mail_to_link('john.doe','example.com','Feedback about your site...');
</script>
<noscript>
<em>Email address protected by JavaScript. Activate JavaScript to see the email.</em>
</noscript>
Because I have been getting email via Gmail since 2005, spam is pretty much a non-issue. So, I can't speak of how effective this method is. You might want to read this study (although it's old) that produced this graph:
Have a look at this way, pretty clever and using css.
CSS
span.reverse {
unicode-bidi: bidi-override;
direction: rtl;
}
HTML
<span class="reverse">moc.rehtrebttam#retsambew</span>
The CSS above will then override the reading direction and present the text to the user in the correct order.
Hope it helps
Cheers
Not my idea originally but I can't find the author:
<a href="mailto:coxntact#domainx.com"
onmouseover="this.href=this.href.replace(/x/g,'');">link</a>
Add as many x's as you like. It works perfectly to read, copy and paste, and can't be read by a bot.
I generally don't bother. I used to be on a mailing list that got several thousand spams every day. Our spam filter (spamassassin) let maybe 1 or 2 a day through. With filters this good, why make it difficult for legitimate people to contact you?
Invent your own crazy email address obfuscation scheme. Doesn't matter what it is, really, as long as it's not too similar to any of the commonly known methods.
The problem is that there really isn't a good solution to this, they're all either relatively simple to bypass, or rather irritating for the user. If any one method becomes prevalent, then someone will find a way around it.
So rather than looking for the One True email address obfuscation technique, come up with your own. Count on the fact that these bot authors don't care enough about your site to sit around writing a thing to bypass your slightly crazy rendering-text-with-css-and-element-borders or your completely bizarre, easily-cracked javascript encryption. It doesn't matter if it's trivial, nobody will bother trying to bypass it just so they can spam you.
I think the only foolproof method you can have is creating a Contact Me page that is a form that submits to a script that sends to your email address. That way, your address is never exposed to the public at all. This may be undesirable for some reason, but I think it's a pretty good solution. It often irks me when I'm forced to copy/paste someone's email address from their site to my mail client and send them a message; I'd rather do it right through a form on their site. Also, this approach allows you to have anonymous comments sent to you, etc. Just be sure to protect your form using some kind of anti-bot scheme, such as a captcha. There are plenty of them discussed here on SO.
You can protect your email address with reCAPTCHA, they offer a free service so people have to enter a CAPTCHA (Completely Automated Public Turing test to tell Computers and Humans Apart) to see your email: https://www.google.com/recaptcha/admin#mailhide
I've written an encoder (source) that uses all kinds of parsing tricks that I could think of (different kinds of HTML entities, URL encoding, comments, multiline attributes, soft hyphens, non-obvious structure of mailto: URL, etc)
It doesn't stop all harvesters, but OTOH it's completely standards-compliant and transparent to the users.
Another IMHO good approach (which you can use in addition to tricky encoding) is along lines of:
<a href="mailto:userhatestogetspam#example.com"
onclick="this.href=this.href.replace(/hatestogetspam/,'')">
If you have php support, you can do something like this:
<img src="scriptname.php">
And the scriptname.php:
<?php
header("Content-type: image/png");
// Your email address which will be shown in the image
$email = "you#yourdomain.com";
$length = (strlen($email)*8);
$im = #ImageCreate ($length, 20)
or die ("Kann keinen neuen GD-Bild-Stream erzeugen");
$background_color = ImageColorAllocate ($im, 255, 255, 255); // White: 255,255,255
$text_color = ImageColorAllocate ($im, 55, 103, 122);
imagestring($im, 3,5,2,$email, $text_color);
imagepng ($im);
?>
I know my answer won't be liked by many but please consider the points outlined here before thumbing down.
Anything easily machine readable will be easily machine readable by the spammers. Even though their actions seem stupid to us, they're not stupid people. They're innovative and resourceful. They do not just use bots to harvest e-mails, they have a plethora of methods at their disposal and in addition to that, they simply pay for good fresh lists of e-mails. What it means is, that they got thousands of black-hat hackers worldwide to execute their jobs. People ready to code malware that scrape the screens of other peoples' browsers which eventually renders any method you're trying to achieve useless. This thread has already been read by 10+ such people and they're laughing at us. Some of them may be even bored to tears to find out we cannot put up a new challenge to them.
Keep in mind that you're not eventually trying to save your time but the time of others. Because of this, please consider spending some extra time here. There is no easy-to-execute magic bullet that would work. If you work in a company that publishes 100 peoples' e-mails on the site and you can reduce 1 spam e-mail per day per person, we're talking about 36500 spam emails a year. If deleting such e-mail takes 5 seconds on average, we're talking about 50 working hours yearly. Not to mention the reduced amount of annoyance. So, why not spend a few hours on this?
It's not only you and the people who receive the e-mail that consider time an asset. Therefore, you must find a way to obfuscate the e-mail addresses in such way, that it doesn't pay off to crack it. If you use some widely used method to obfuscate the e-mails, it really pays off to crack it. Since as an result, the cracker will get their hands on thousands, if not tens or hundreds of thousands of fresh e-mails. And for them, they will get money.
So, go ahead and code your own method. This is a rare case where reinventing the wheel really pays off. Use a method that is not machine readable and one which will preferably require some user interaction without sacrificing the user experience.
I spent some 20 minutes to code off an example of what I mean. In the example, I used KnockoutJS simply because I like it and I know you won't probably use it yourself. But it's irrelevant anyway. It's a custom solution which is not widely used. Cracking it won't pose a reward for doing it since the method of doing it would only work on a single page in the vast internet.
Here's the fiddle: http://jsfiddle.net/hzaw6/
The below code is not meant to be an example of good code. But just a quick sample of code which is very hard for machine to figure out we even handle e-mails in here. And even if it could be done, it's not gonna pay off to execute in large scale.
And yes, I do know it doesn't work on IE = lte8 because of 'Unable to get property 'attributes' of undefined or null reference' but I simply don't care because it's just a demo of method, not actual implementation, and not intended to be used on production as it is. Feel free to code your own which is cooler, technically more solid etc..
Oh, and never ever ever name something mail or email in html or javascript. It's just way too easy to scrape the DOM and the window object for anything named mail or email and check if it contains something that matches an e-mail. This is why you don't want any variables ever that would contain e-mail in it's full form and this is also why you want user to interact with the page before you assign such variables. If your javascript object model contains any e-mail addresses on DOM ready state, you're exposing them to the spammers.
The HTML:
<div data-bind="foreach: contacts">
<div class="contact">
<div>
<h5 data-bind="text: firstName + ' ' + lastName + ' / ' + department"></h5>
<ul>
<li>Phone: <span data-bind="text: phone"></span></li>
<li>E-mail <span data-bind="visible: $root.msgMeToThis() != ''"><input class="merged" data-bind="value: mPrefix" readonly="readonly" /><span data-bind="text: '#' + domain"></span></span></li>
</ul>
</div>
</div>
</div>
The JS
function ViewModel(){
var self = this;
self.contacts = ko.observableArray([
{ firstName:'John', mPrefix: 'john.doe', domain: 'domain.com', lastName: 'Doe', department: 'Sales', phone: '+358 12 345 6789' },
{ firstName:'Joe', mPrefix: 'joe.w', domain: 'wonder.com', lastName: 'Wonder', department: 'Time wasting', phone: '+358 98 765 4321' },
{ firstName:'Mike', mPrefix: 'yo', domain: 'rappin.com', lastName: 'Rophone', department: 'Audio', phone: '+358 11 222 3333' }
]);
self.msgMeToThis = ko.observable('');
self.reveal = function(m, e){
var name = e.target.attributes.href.value;
name = name.replace('#', '');
self.msgMeToThis(name);
};
}
var viewModel = new ViewModel();
ko.applyBindings(viewModel);
You can try to hide characters using html entities in hexa (ex: &#x40 for #).
This is convenient solution, as a correct browser will translate it, and you can have a normal link.
The drawback is that a bot can translate it theorically, but it's a bit unusual.
I use this to protect my e-mail on my blog.
Another solution is to use javascript to assemble part of the address and to decode on-the-fly the address.
The drawback is that a javascript-disabled browser won't show your adress.
The most effective solution is to use an image, but it's a pain for the user to have to copy the address by hand.
Your solution is pretty good, as you only add a drawback (writing manually the #) only for user that have javascript disabled.
You can also be more secure with :
onclick="this.href='mailto:' + 'admin' + '#' + 'domain.com'"
One of my favorite methods is to obfuscate the email address using php, a classic example is to convert the characters to HEX values like so:
function myobfiscate($emailaddress){
$email= $emailaddress;
$length = strlen($email);
for ($i = 0; $i < $length; $i++){
$obfuscatedEmail .= "&#" . ord($email[$i]).";";
}
echo $obfuscatedEmail;
}
And then in my markup I'll simply call it as follows:
<a href="mailto:<?php echo myobfiscate('someone#somewhere.com'); ?>"
title="Email me!"><?php echo myobfiscate('someone#somewhere.com');?> </a>
Then examine your source, you'll be pleasantly surprised!
I wouldn't bother -- it is fighting the SPAM war at the wrong level. Particularly for company web sites I think it makes things look very unprofessional if you have anything other than the straight text on the page with a mailto hyperlink.
There is so much spam flying around that you need good filtering anyway, and any bot is going end up understanding all the common tricks anyway.
HTML:
<a href="#" class="--mailto--john--domain--com-- other classes goes here" />
JavaScript, using jQuery:
// match all a-elements with "--mailto--" somehere in the class property
$("a[class*='--mailto--']").each(function ()
{
/*
for each of those elements use a regular expression to pull
out the data you need to construct a valid e-mail adress
*/
var validEmailAdress = this.className.match();
$(this).click(function ()
{
window.location = validEmailAdress;
});
});
Spambots won't interpret this, because it is a lesser-known method :)
First, define the css:
email:before {
content: "admin";
}
email:after {
content: "#example.com";
}
Now, wherever you want to display your email, simply insert the following HTML:
<div id="email"></div>
And tada!
I use a very simple combination of CSS and jQuery which displays the email address correctly to the user and also works when the anchor is clicked or hovered:
HTML:
moc.elpmaxe#em
CSS:
#lnkMail {
unicode-bidi: bidi-override;
direction: rtl;
}
jQuery:
$('#lnkMail').hover(function(){
// here you can use whatever replace you want
var newHref = $(this).attr('href').replace('spam', 'com');
$(this).attr('href', newHref);
});
Here is a working example.
I don't bother. You'll only annoy sophisticated users and confuse unsophisticated users. As others have said, Gmail provides very effective spam filters for a personal/small business domain, and corporate filters are generally also very good.
The best method hiding email addresses is only good until bot programmer discover this "encoding" and implement a decryption algorithm.
The JavaScript option won't work long, because there are a lot of crawler interpreting JavaScript.
There's no answer, imho.
!- Adding this for reference, don't know how outdated the information might be, but it tells about a few simple solutions that don't require the use of any scripting
After searching for this myself i came across this page but also these pages:
http://nadeausoftware.com/articles/2007/05/stop_spammer_email_harvesters_obfuscating_email_addresses
try reversing the emailadress
Example plain HTML:
<bdo dir="rtl">moc.elpmaxe#nosrep</bdo>
Result : person#example.com
The same effect using CSS
CSS:
.reverse { unicode-bidi:bidi-override; direction:rtl; }
HTML:
<span class="reverse">moc.elpmaxe#nosrep</span>
Result : person#example.com
Combining this with any of earlier mentioned methods may even make it more effective
One easy solution is to use HTML entities instead of actual characters.
For example, the "me#example.com" will be converted into :
email me
A response of mine on a similar question:
I use a very simple combination of CSS and jQuery which displays the
email address correctly to the user and also works when the anchor is
clicked:
HTML:
moc.elpmaxe#em
CSS:
#lnkMail {
unicode-bidi: bidi-override;
direction: rtl;
}
jQuery:
$('#lnkMail').hover(function(){
// here you can use whatever replace you want
var newHref = $(this).attr('href').replace('spam', 'com');
$(this).attr('href', newHref);
});
Here is a working example.
Here is my working version:
Create somewhere a container with a fallback text:
<div id="knock_knock">Activate JavaScript, please.</div>
And add at the bottom of the DOM (w.r.t. the rendering) the following snippet:
<script>
(function(d,id,lhs,rhs){
d.getElementById(id).innerHTML = "<a rel=\"nofollow\" href=\"mailto"+":"+lhs+"#"+rhs+"\">"+"Mail"+"<\/a>";
})(window.document, "knock_knock", "your.name", "example.com");
</script>
It adds the generated hyperlink to the specified container:
<div id="knock_knock"><a rel="nofollow" href="your.name#example.com">Mail</a></div>
In addition here is a minified version:
<script>(function(d,i,l,r){d.getElementById(i).innerHTML="<a rel=\"nofollow\" href=\"mailto"+":"+l+"#"+r+"\">"+"Mail"+"<\/a>";})(window.document,"knock_knock","your.name","example.com");</script>
A neat trick is to have a div with the word Contact and reveal the email address only when the user moves the mouse over it. E-mail can be Base64-encoded for extra protection.
Here's how:
<div id="contacts">Contacts</div>
<script>
document.querySelector("#contacts").addEventListener("mouseover", (event) => {
// Base64-encode your email and provide it as argument to atob()
event.target.textContent = atob('aW5mb0BjbGV2ZXJpbmcuZWU=')
});
</script>
The only safest way is of course not to put the email address onto web page in the first place.
Use a contact form instead. Put all of your email addresses into a database and create an HTML form (subject, body, from ...) that submits the contents of the email that the user fills out in the form (along with an id or name that is used to lookup that person's email address in your database) to a server side script that then sends an email to the specified person. At no time is the email address exposed. You will probably want to implement some form of CAPTCHA to deter spambots as well.
There are probably bots that recognize the [at] and other disguises as # symbol. So this is not a really effective method.
Sure you could use some encodings like URL encode or HTML character references (or both):
// PHP example
// encodes every character using URL encoding (%hh)
function foo($str) {
$retVal = '';
$length = strlen($str);
for ($i=0; $i<$length; $i++) $retVal.=sprintf('%%%X', ord($str[$i]));
return $retVal;
}
// encodes every character into HTML character references (&#xhh;)
function bar($str) {
$retVal = '';
$length = strlen($str);
for ($i=0; $i<$length; $i++) $retVal.=sprintf('&#x%X;', ord($str[$i]));
return $retVal;
}
$email = 'user#example.com';
echo 'mail me';
// output
// mail me
But as it is legal to use them, every browser/e-mail client should handle these encodings too.
One possibility would be to use isTrusted property (Javascript).
The isTrusted read-only property of the Event interface is a Boolean
that is true when the event was generated by a user action, and false
when the event was created or modified by a script or dispatched via
EventTarget.dispatchEvent().
eg in your case:
getEmail() {
if (event.isTrusted) {
/* The event is trusted */
return 'your-email#domain.com';
} else {
/* The event is not trusted */
return 'chuck#norris.com';
}
}
⚠ IE isn't compatible !
Read more from doc: https://developer.mozilla.org/en-US/docs/Web/API/Event/isTrusted
I make mine whateverDOC#whatever.com and then next to it I write "Remove the capital letters"
Another, possibly unique, technique might be to use multiple images and a few plain-text letters to display the address. That might confuse the bots.