Author: Alexander

  • Exotic HTTP headers

    Hello! This article will illustrate the result of applying some important and exotic HTTP headers, most of which are related to security.

    X-XSS-Protection

    Attack XSS (cross-site scripting) is a type of attack in which malicious code can be embedded in the target page.
    For example like this:

    <h1>Hello, <script>alert('hacked')</script></h1>

    This type of attacks easy to detect and the browser may handle it: if the source code contains part of the request, it may be a threat.

    And the title X-XSS-Protection manages the behavior of the browser.

    Accepted values:

    • 0 the filter is turned off
    • 1 filter is enabled. If the attack is detected, the browser will remove the malicious code.
    • 1; mode=block. The filter is enabled, but if the attack is detected, the page will not be loaded by the browser.
    • 1; report=http://domain/url. the filter is enabled and the browser will clear the page from malicious code while reporting the attempted attack. Here, we use a function Chromium for reporting violation of content security policy (CSP) to a specific address.

    Create a web server sandbox on node.js to see how it works.

    
    var express = require('express')
    var app = express()
    app.use((req, res) => {
     if (req.query.xss) res.setHeader('X-XSS-Protection', req.query.xss)
    res.send(`<h1>Hello, ${req.query.user || 'anonymous'}</h1>`)
    })
    
    app.listen(1234)
    
    

    I will use Google Chrome 55.

    No title
    http://localhost:1234/?user=%3Cscript%3Ealert(%27hacked%27)%3C/script%3E

    Nothing happens, the browser will successfully block the attack. Chrome, by default, blocks the threat and reported it to the console.

    It even highlights the problem area in the source code.

    X-XSS-Protection: 0

    http://localhost:1234/?user=%3Cscript%3Ealert(%27hacked%27)%3C/script%3E&xss=0

    Oh no!

    X-XSS-Protection: 1

    http://localhost:1234/?user=%3Cscript%3Ealert(%27hacked%27)%3C/script%3E&xss=1

    Page was cleared because of the explicit title.0

    X-XSS-Protection: 1; mode=block

    http://localhost:1234/?user=%3Cscript%3Ealert(%27hacked%27)%3C/script%3E&xss=1;%20mode=block

    In this case, the attack will be prevented by blocking the page load.

    X-XSS-Protection: 1; report=http://localhost:1234/report

    http://localhost:1234/?user=%3Cscript%3Ealert(%27hacked%27)%3C/script%3E&xss=1;%20report=http://localhost:1234/report

    The attack is prevented and a message is sent to the appropriate address.

    X-Frame-Options

    With this title you can protect yourself from the so-called Clickjacking.

    Imagine that the attacker has a channel on YouTube and he wants more followers.

    He can create a page with a button “Do not press”, which would mean that everyone will click on it necessarily. But over the button is completely transparent iframe and in this frame hides the channel page with the subscription button. Therefore, when you press the button, in fact, a user subscribes to a channel, unless of course, he was logged into YouTube.

    We will demonstrate that.

    First, you need to install the extension to ignore this header.

    Create a simple page.

    
    <style>
    button { background: red; color: white; padding: 10px 20px; border: none; cursor: pointer; }
    iframe { opacity: 0.8; z-index: 1; position: absolute; top: -570px; left: -80px; width: 500px; height: 650px; }</style>
    
    <button>Do not click his button!</button>
    <iframe src="https://youtu.be/dQw4w9WgXcQ?t=3m33s"></iframe>
    

    As you can see, I have placed the frame with the subscription right over the button (z-index: 1) and so if you try to click it, you actually press the frame. In this example, the frame is not fully transparent, but it can be fixed with the value of opacity: 0.

    In practice, this doesn’t work, because YouTube set the desired heading, but the sense of threat, I hope, is clear.

    To prevent the page to be used in the frame need to use the title X-Frame-Options.

    Accepted values:

    • deny not load the page at all.
    • sameorigin not load if the source is not the same.
    • allow-from: DOMAIN you can specify the domain from which the page can be loaded in a frame.

    We need a web server to demonstrate

    var express = require('express')
    
     
    for (let port of [1234, 4321]) {
     var app = express()
    app.use('/iframe', (req, res) => res.send(`<h1>iframe</h1><iframe src="//localhost:1234?h=${req.query.h || ''}"></iframe>`))
    app.use((req, res) => {
      if (req.query.h) res.setHeader('X-Frame-Options', req.query.h)
    res.send('<h1>Website</h1>')
    })
    app.listen(port)
    }
    

    No title

    Everyone will be able to build our website on localhost:1234 in the frame.

    X-Frame-Options: deny

    The page cannot be used at all in the frame.

    X-Frame-Options: sameorigin

    Only pages with the same source will be able to be built into the frame. The sources are the same, if the domain, port and protocol are the same.

    X-Frame-Options: allow-from localhost:4321

    It seems that Chrome ignores this option, because there is a header Content-Security-Policy (about it will be discussed below). It does not work in Microsoft Edge.

    Below Mozilla Firefox.

    X-Content-Type-Options

    This header prevents attacks spoofing MIME type (<script src=”script.txt”>) or unauthorized hotlinking (<script src=”https://raw.githubusercontent.com/user/repo/branch/file.js”>)

    
    var express = require('express')
    var app = express()
    
    app.use('/script.txt', (req, res) => {
      if (req.query.h) res.header('X-Content-Type-Options', req.query.h)
    res.header('content-type', 'text/plain')
    res.send('alert("hacked")')
    })
    
    app.use((req, res) => {
    res.send(`<h1>Website</h1><script src="/script.txt?h=${req.query.h || ''}"></script>`
    })
    app.listen(1234)
    

    No title

    http://localhost:1234/

    Though script.txt is a text file with type text/plain, it will be launched as a script.

    X-Content-Type-Options: nosniff

    http://localhost:1234/?h=nosniff

    This time the types do not match and the file will not be executed.

    Content-Security-Policy

    It is a relatively new title and helps to reduce the risks of XSS attacks in modern browsers by specifying in the title what resources can be loaded on the page.

    For example, you can ask the browser do not execute inline-scripts and download files only from one domain. Inline-scripts can look not only like <script>…</script>, but also as <h1 onclick=”…”>.

    Let’s see how it works.

    
    var request = require('request')
    
    var express = require('express')
    
     
    
    for (let port of [1234, 4321]) {
    
    var app = express()
    
    app.use('/script.js', (req, res) => {
    
    res.send(`document.querySelector('#${req.query.id}').innerHTML = 'changed ${req.query.id}-script'`)
    
    })
    
    app.use((req, res) => {
    
    var csp = req.query.csp
    
    if (csp) res.header('Content-Security-Policy', csp)
    
    res.send(`
    
    <html>
    
    <body>
    
    <h1>Hello, ${req.query.user || 'anonymous'}</h1>
    
    <p id="inline">this will changed inline-script?</p>
    
    <p id="origin">this will changed origin-script?</p>
    
    <p id="remote">this will changed remote-script?</p>
    
    <script>document.querySelector('#inline').innerHTML = 'changed inline-script'</script>
    
    <script src="/script.js?id=origin"></script>
    
    <script src="//localhost:1234/script.js?id=remote"></script>
    
    </body>
    
    </html>
    
    `)
    
    })
    
    app.listen(port)
    
    }
    

    No title

    It works as you would expect

    Content-Security-Policy: default-src ‘none’

    http://localhost:4321/?csp=default-src%20%27none%27&user=%3Cscript%3Ealert(%27hacked%27)%3C/script%3E

    default-src applies a rule to all resources (images, scripts, frames, etc.), the value ‘none’ disables all. Below is shown what happens and the errors displayed in the browser.

    Chrome refused to run any scripts. In this case, you can’t even upload a favicon.ico.

    Content-Security-Policy: default-src ‘self’

    http://localhost:4321/?csp=default-src%20%27self%27&user=%3Cscript%3Ealert(%27hacked%27)%3C/script%3E

    Now it is possible to use the resources from one source but still cannot run external and inline-scripts.

    Content-Security-Policy: default-src ‘self’; script-src ‘self’ ‘unsafe-inline’

    http://localhost:4321/?csp=default-src%20%27self%27;%20script-src%20%27self%27%20%27unsafe-inline%27&user=%3Cscript%3Ealert(%27hacked%27)%3C/script%3E

    This time we let the execution and inline-scripts. Please note that XSS attack in the request was blocked too. But this will not happen if at the same time deliver and unsafe-inline and X-XSS-Protection: 0.

    Other values

    On the website, content-security-policy.com beautifully had shown many examples.

    • default-src ‘self’ allowed resources only from one source
    • script-src ‘self’ www.google-analytics.com ajax.googleapis.com allow Google Analytics, Google AJAX CDN, and resources from one source.
    • default-src ‘none’; script-src ‘self’; connect-src ‘self’; img-src ‘self’; style-src ‘self’; allow images, scripts, AJAX and CSS from one source and prohibit the downloading of any other resources. For most sites this is a good initial setting.

    I didn’t check, but I think that the following headers are equivalent:

    • frame-ancestors ‘none’ and X-Frame-Options: deny
    • frame-ancestors ‘self’ and X-Frame-Options: sameorigin
    • frame-ancestors localhost:4321 and X-Frame-Options: allow-from localhost:4321
    • script-src ‘self’ without ‘unsafe-inline’ and X-XSS-Protection: 1

    If you look at the headers facebook.com or twitter.com it is possible to notice that these sites use a lot of CSP.

    Strict-Transport-Security

    HTTP Strict Transport Security (HSTS) is a mechanism for security policy, which helps protect the website from attempts by an unsecured connection.

    Let’s say that we want to connect to facebook.com. If you don’t specify before requesting https://, protocol, by default, will be selected HTTP and therefore the request will look like http://facebook.com.

    
    $ curl -I facebook.com
    HTTP/1.1 301 Moved Permanently
    Location: https://facebook.com/
    

    After that, we will be redirected to the secure version of Facebook.

    If you connect to a public WiFi hotspot, which is owned by the attacker, the request may be intercepted and instead facebook.com the attacker may substitute a similar page to know the username and password.

    To guard against such an attack, you can use the aforementioned title that will tell the client the next time to use the https-version of the site.

    
    $ curl -I https://www.facebook.com/
    HTTP/1.1 200 OK
    Strict-Transport-Security: max-age=15552000; preload
    

    If the user was logged into Facebook at home and then tried to open it from an unsafe access point, he is not in danger, because browsers remember the title.

    But what happens if you connect to the unsecured network first time? In this case, the protection will not work.

    But browsers have a trump card in this case. They have a predefined list of domains for which should be used HTTPS only.

    You can send your domain at this address. It is also possible to find out whether the header is used correctly.

    Accepted values:

    • max-age=15552000 the time in seconds that the browser should remember the title.
    • includeSubDomains If you specify this optional value, the header applies to all subdomains.
    • preload if the site owner wants the domain got into a predefined list that is supported by Chrome (and used by Firefox and Safari).

    And if you need to switch to HTTP before the expiration of max-age or if you set preload? You can put the value max-age value=0 and then the navigation rule to the https version will stop to work.

    Public-Key-Pins

    HTTP Public Key Pinning (HPKP) is a mechanism for security policy that allows HTTPS sites to protect against malicious use of fake or fraudulent certificates.

    Accepted values:

    • pin-sha256=”<sha256>” in quotes is encoded using Base64 thumbprint of the Subject Public Key Information (SPKI). You can specify multiple pins for different public keys. Some browsers in the future may use other hashing algorithms besides SHA-256.
    • max-age=<seconds> the time, in seconds, that for access to the site need to use only the listed keys.
    • includeSubDomains if you specify this optional parameter, the title applies to all subdomains.
    • report-uri=”<URL>” if you specify URL, then when a validation error key, the corresponding message will be sent to the specified address.

    Instead of the title Public-Key-Pins, you can use Public-Key-Pins-Report-Only, in this case, it will only send the error messages to match the keys, but the browser will still load the page.

    So does Facebook:

    
    $ curl -I https://www.facebook.com/
    
    HTTP/1.1 200 OK
    
    ...
    
    Public-Key-Pins-Report-Only:
    
    max-age=500;
    
    pin-sha256="WoiWRyIOVNa9ihaBciRSC7XHjliYS9VwUGOIud4PB18=";
    
    pin-sha256="r/mIkG3eEpVdm+u/ko/cwxzOMo1bk4TyHIlByibiA5E=";
    
    pin-sha256="q4PO2G2cbkZhZ82+JgmRUyGMoAeozA+BSXVXQWB8XWQ=";
    
    report-uri="http://reports.fb.com/hpkp/"
    

    Why is it necessary? Not enough of trusted certification authorities (CA)?

    An attacker can create a certificate for facebook.com and by tricking the user to add it to your list of trusted certificates, or it can be an administrator.

    Let’s try to create a certificate for facebook.

    
    sudo mkdir /etc/certs
    
    echo -e 'US\nCA\nSF\nFB\nXX\nwww.facebook.com\nn*@**am.org' | \
    
    sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
    
    -keyout /etc/certs/facebook.key \
    
    -out /etc/certs/facebook.crt
    

    And make it trusted in the local system.

    
    # curl
    
    sudo cp /etc/certs/*.crt /usr/local/share/ca-certificates/
    
    sudo update-ca-certificates
    
    # Google Chrome
    
    sudo apt install libnss3-tools -y
    
    certutil -A -t "C,," -n "FB" -d sql:$HOME/.pki/nssdb -i /etc/certs/facebook.crt
    
    # Mozilla Firefox
    
    #certutil -A -t "CP,," -n "FB" -d sql:`ls -1d $HOME/.mozilla/firefox/*.default | head -n 1` -i /etc/certs/facebook.crt
    

    Now run the web server using this certificate.

    
    var fs = require('fs')
    
    var https = require('https')
    
    var express = require('express')
    
     
    
    var options = {
    
    key: fs.readFileSync(`/etc/certs/${process.argv[2]}.key`),
    
    cert: fs.readFileSync(`/etc/certs/${process.argv[2]}.crt`)
    
    }
    
     
    
    var app = express()
    
    app.use((req, res) => res.send(`<h1>hacked</h1>`))
    
    https.createServer(options, app).listen(443)
    

    Switch to the server

    
    echo 127.0.0.1 www.facebook.com | sudo tee -a /etc/hosts
    
    sudo node server.js facebook
    

    Let’s see what happened

    
    $ curl https://www.facebook.com
    
    <h1>hacked</h1>
    

    Great. curl validates the certificate.

    So as I already went to Facebook and Google Chrome has seen its headers, it should report the attack but to allow the page, right?

    Nope. Keys are not checked because of local root certificate [Public key pinning bypassed]. This is interesting…

    Well, and what about www.google.com?

    
    echo -e 'US\nCA\nSF\nGoogle\nXX\nwww.google.com\nn*@**am.org' | \
    
    sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
    
    -keyout /etc/certs/google.key \
    
    -out /etc/certs/google.crt
    
    sudo cp /etc/certs/*.crt /usr/local/share/ca-certificates/
    
    sudo update-ca-certificates
    
    certutil -A -t "C,," -n "Google" -d sql:$HOME/.pki/nssdb -i /etc/certs/google.crt
    
    echo 127.0.0.1 www.google.com | sudo tee -a /etc/hosts
    
    sudo node server.js google
    

    The same result. I think this is a feature.

    But in any case, if you do not add these certificates to the local store, open websites will not work because the option to continue with an insecure connection in Chrome or add an exception in Firefox will not.

    Content-Encoding: br

    Data is compressed with Brotli.

    The algorithm promises better compression than gzip and comparable speed unzipping. Supports Google Chrome.

    Of course, there is a module for in node.js.

    
    var shrinkRay = require('shrink-ray')
    
    var request = require('request')
    
    var express = require('express')
    
     
    
    request('https://www.gutenberg.org/files/1342/1342-0.txt', (err, res, text) => {
    
    if (err) throw new Error(err)
    
    var app = express()
    
    app.use(shrinkRay())
    
    app.use((req, res) => res.header('content-type', 'text/plain').send(text))
    
    app.listen(1234)
    
    })
    

    Original size: 700 KB

    Brotli: 204 KB

    Gzip: 241 KB

    Timing-Allow-Origin

    Using the Resource Timing API, you can find out how much time took the processing of resources on the page.

    Because the information of load-time may be used to determine whether the user visited the page before this (paying attention to the fact that resources can be cached), a standard is considered to be vulnerable, if you give this information to any hosts.

    
    <script>
    
    setTimeout(function() {
    
    console.log(window.performance.getEntriesByType('resource'))
    
    }, 1000)
    
    </script>
    
     
    
    <img src="http://placehold.it/350x150">
    
    <img src="/local.gif">
    

    It seems that if you do not specify Timing-Allow-Origin, then get detailed information about the time of the operations (the search domain, for example) is possible only for resources with one source.

    You can use this:

    • Timing-Allow-Origin: *
    • Timing-Allow-Origin: http://foo.com http://bar.com

    Alt-Svc

    The Alternative Services allow resources to be in different parts of the network and access to them can be obtained using different configurations of the protocol.

    This is used in Google:

    • alt-svc: quic=”:443″; ma=2592000; v=”36,35,34″

    This means that the browser, if it wish, can use the QUIC, it is HTTP over UDP, over port 443 the next 30 days (ma = 2592000 seconds, or 720 hours, i.e. 30 days). I have no idea what means the parameter v, version?

    P3P

    Below are some P3P headers that I have seen:

    • P3P: CP=«This is not a P3P policy! See support.google.com/accounts/answer/151657?hl=en for more info.»
    • P3P: CP=«Facebook does not have a P3P policy. Learn why here: fb.me/p3p»

    Some browsers require that cookies of third parties supported the P3P protocol for designation of confidentiality measures.

    The organization, founded P3P, the world wide web Consortium (W3C) halted work on the protocol a few years ago due to the fact that modern browsers don’t end up to support protocol. As a result, P3P is outdated and does not include technologies that are now used in a network, so most sites do not support P3P.

    I didn’t go too far, but apparently the header is needed for IE8 to accept cookies from third parties.

    For example, if IE privacy settings are high, then all cookies from sites that do not have a compact privacy policy will be blocked, but those who have headlines similar to the above, will not be blocked.

    Which of the following HTTP headers You use in projects?

    X-XSS-Protection
    X-Frame-Options
    X-Content-Type-Options
    Content-Security-Policy
    Strict-Transport-Security
    Public-Key-Pins
    Content-Encoding
    Timing-Allow-Origin
    Alt-Svc
    P3P
    Other

    This text is a translation of the article “Экзотичные заголовки HTTP”  published by @A3a on habrahabr.ru.

    About the CleanTalk service

    CleanTalk is a cloud service to protect websites from spambots. CleanTalk uses protection methods that are invisible to the visitors of the website. This allows you to abandon the methods of protection that require the user to prove that he is a human (captcha, question-answer etc.).

  • About SomeInspiration.com

    Hello, I’m Francis O’Neill, and, among other things, such as looking after the website I’m about to tell you about, I now view myself as a writer. I write on spiritual health and mind, body & spirit topics. I have a couple of books out at this time. In many respects this also encapsulates my business.

    I’ve just hit the big seven-o so I’ve been around the block a few times – or as I like to say, I’ve been around the Sun a few times. I could swear the Earth is speeding up on its journey. It seems I get back to the starting point that bit quicker with each passing year.

    As you may guess by my name, I’m Irish by birth. I have however lived in England for most of my life.

    Road to Damascus

    Let me give you a brief backdrop to my direction of travel. This is germane to what I’m doing on the Web.

    Back in my twenties I wasn’t so spiritually inclined or oriented as I consider myself now. I had by then become secular and existential in my beliefs. I had walked away from a Roman Catholic upbringing. I was in my teens when I began to question my beliefs. Later I went motorcycle racing as something far more preferable to do on Sundays.

    It was from this position, and my developing interest in psychology, that I later came across a book I want to just mention. This was by C.G. Jung; his Memories, Dreams, Reflections. Reading this book literally was a road to Damascus experience for me, a turning point. From that point on I began to look at things differently, exploring life from a different perspective. It helped to give structure to my own thoughts and experiences. And it has since become a lifelong endeavour, that is to gain a clearer understanding of the human situation from a spiritual viewpoint – and to write about it in posts and books.

    My first book, Life and Death: Making Sense of It, is an outcome of my search.  It took some years to research and write. I see the work as a reporting back on what I have discovered on my travels.

    The book could be a challenging perspective for anyone who has yet to think out of the box regarding their existence – or also for the person who has been brought up in a religion that doesn’t incorporate the concept of previous existence and karma. If it interests you, you can easily find out more, and get hold of the book’s Introduction, off lifeanddeaththebook.com.

    Just to finish the bit about me, I have a degree is in Humanistic and Transpersonal Psychology. I’m also a practising astrologer having studied with the Faculty of Astrological Studies and the Mayo School of Astrology in the UK. I’ve spent a good chunk of my life as a field archaeologist, supervising excavations, and also as a qualified lecturer in adult education.

    I live in the Cotswolds (UK) with my partner, Annie Locke. Annie is a musician/composer of essentially classical and romantic melody; that a lot of people also find nostalgic and relaxing to listen to.

    Some Inspiration website

    I began the SomeInspiration.com website back in 2012. This was after being made redundant from a teaching post the year before. Redundancy was a blow but it was also an exciting time of potential. I was given the freedom to begin new adventures.

    From the bat, the site was intended to carry, what I considered, interesting or helpful and inspiring posts, gain visitors and be able to help me to make a living – the latter through affiliate marketing.

    In practice this has entailed promoting my partner’s music plus self-help products. The plan was to also include my book/s at a later stage.

    Although I had been building websites from some time back, using html, for this website I used WordPress. I looked into a number of content management systems and decided upon WP. I love it, and wouldn’t use any other program now. It never ceases to amaze me the work and sophistication that goes into its development – and the amazing array of plugins (such as CleanTalk), which make life so much easier than it was in the early days. To my mind it is one of the better reasons for the Web being in existence.

    Today the website continues to provide the service it more or less began as. But there have been one or two important changes.

    I discovered I was getting a raw deal with the self-hypnosis company I originally had affiliate links with, and so cancelled my relations with them.

    There has also been a change of identity from my earlier use of the site. The site is now more focussed on mind, body & spirit topics than previously was the case.

    Issues in the development of the site

    This mind, body & spirit identity is really a recent development. A website, or blog, having a clear identity, I know now, is key to helping getting traffic, but it took me a while to realise this. When, earlier this year, I decided to create a new website for my first book, I found myself in a bit of a quandary. The Some Inspiration site carried posts that were more appropriate for the book site.

    Rather than replicate them, or cross-link them, I decided to move them across and use redirects. It took a bit of sorting. It was at this juncture that I decided upon the “mind, body & spirit” focus for the site, while the book site was better served carrying articles/posts akin to the content of the book, which is primarily concerned with “spiritual health.” Meanwhile I had also decided to use Some Inspiration as the publisher for my books.

    If mind, body & spirit, and spiritual health sound like the same area of interest, you’re right. They are the same but at different levels, as I perceive them. People interested in mind, body & spirit matters (largely of a self-help nature), are not necessarily interested in, for example, UFOs, ghosts, the paranormal, or the Other Side – as covered in the book.

    Going forward

    I’m now happier with the site and the direction it is going in. There is still a lot more to do to bring it up to speed in the way I envision it. I’m bringing on-board new products. My second book, Steps to Health, Wealth & Inner Peace, is one of those products that is a good fit with the site. I might add that I’m using ClickBank and Amazon for some of my affiliate products.

    All I need now is greater footfall. Well if you are anything like me then getting more traffic is a perennial concern – without which I’m dead in the water, or may as well be. Going forward I’m looking to build more backlinks and to build up my email-list/s as my approach to dealing with this concern. Wish me luck. If you have any tips they are most welcome.

    Well that’s about all I can tell you right now. Stay tuned – and do visit the site. In you write posts, around mind, body & spirit topics, why not consider writing one for Some Inspiration – I won’t bite I promise.

  • New anti-spam checks for WordPress, XenForo, phpBB 3.1, SMF, Bitrix

    We are pleased to announce that we have released new versions of plugins for WordPress, XenForo, phpBB 3.1, SMF, Bitrix.

    In the new version, we have added some new checks for spam to improve anti-spam service.

    Mouse tracking and Time zone monitoring give good results against spam bots which simulate the behavior of real visitors.

    These checks for other CMS will be added soon.

    Please, update your anti-spam plugins for latest version:

    WordPress
    XenForo
    phpBB 3.1
    Simple Machines Forum
    Bitrix

  • Spam Statistics and Trends for a year

    Spam Statistics and Trends for a year

    We have published Anti-Spam Statistics and trends for a year.

    • Statistics include numbers of spam attacks for CMS, Sources of spam by countries.
    • Average spam attacks per day and trends for each CMS.
    • The amount of spam in POST queries.

    https://cleantalk.org/spam-stats

  • New version of the Security Service by CleanTalk

    New version of the Security Service by CleanTalk

    As we informed CleanTalk launched its website security project. The service protects administrator control panel from brute-force attacks and records users’ actions.

    Since the 29th of November Security by CleanTalk has become the Cloud Service and now all main data will be available in The Service Dashboard. The cost of the service is $20 per year for 1 website.

    Switching to Cloud Data Storage allows to show more data and use the information more flexible thanks to different filters in your Dashboard.

    In the previous versions all data were being stored in a website database and big amount of information alongside with its operations would affect website speed, all this could give a result of bad website ranking of search engines. Cloud Data Storage is safer than website database. If an intruder could get access to your website then he could delete all data he might be traced with.

    Cloud Service provides data storage for the last 45 days including users action log, brute-force attacks statistics and successful backend logins and you can always get to know who and what actions were made if it is necessary.

  • Blocking emails by a mask

    Dear users!

    CleanTalk has expanded the functions of personal blacklists. We’ve added an ability to filter email addresses by a mask.

    Symbol asterisk “*” means any set of characters.

    Examples:

    name*@example.com (all e-mail addresses with any set of characters after “name” will be blocked).
    *aa**@*****le.com (all e-mail addresses with any set of characters before “aa44” will be blocked).
    *kkk*vvv*@example.com (all e-mail addresses with any set of characters before “kkk”, before “vvv” and after “vvv” will be blocked).

    And so on, you can use any combinations of characters and asterisks to make a mask.

    Instructions how to use the personal blacklists can be found here https://cleantalk.org/help/blacklist-usage

  • Blocking spam by nicknames

    Dear users!

    We are pleased to expand opportunities of Stop Words function.

    Added an ability to use stop words to block users whose nicknames contain certain words. This will allow you to use the service to block users with obscene or containing advertising nicknames.

    How to use Stop-Word Feature:

    • Go to your CleanTalk Control Panel.
    • Choose website you want to apply this feature.
    • Press the line “Settings” under the name of your chosen website.
    • Tick the option “Enable comments test via stop list” and press the button “Save“.
    • The line “Stop List” will appear on the right side of the page, click it to add the words you want to be blocked.

    Please note that the changes will be applied in 10-15 minutes.

    The feature is available after purchasing our Extra Package. Go to your Renewal Licence Page to see the details.

  • Reader mode: Pagination in mobile emails

    Development of responsive design make reading emails on mobile devices easier. On the other hand, the side effect is the fact that to read the massive letters now you need a lot of scrolling. As a result, to the end of the message get only the most persistent readers. If you give people the ability to quickly navigate through email, it would greatly improve the situation.

    The described technique works only in the email application Mail for iPhone (Android version in development).

    Reader mode

    The described technique allows the user to independently control the content of the letter –  with a special button letter transforms in version for reading divided into several pages that can be accessed with a click.

    Activation

    A button to enable “reader mode” is wrapped in a label that switches the checkbox with the id of the cell navigation. To display items in this mode, use the pseudo-class :checked, the menu in the top of the panel is set to position:fixed:

    
    <style>
    
    .toolbar-container{
    
    position:fixed;
    
    top:0px; left:0px;
    
    display:none;
    
    ...
    
    }
    
     
    
    #navbox:checked ~ .toolbar-container{
    
    display:block!important;
    
    }
    
     
    
    #navbox:checked ~ .articles-container{
    
    height:100%;
    
    overflow:hidden;
    
    position:fixed;
    
    top:50px;
    
    left:0px;
    
    }
    
    </style>
    
    
     
    
    <input id="navbox" type="checkbox">
    
    <label for="navbox" >Activate Reader Mode</label>
    
     
    
    <div class="toolbar-container">...hidden toolbar content ... <div>
    
    <div class="articles-container">
    
    article1, article2, article3...
    
    </div>
    

    Pagination of articles

    Article wrapped in two containers. When activated the selector :checked, outer container displays the content on the full width and height of the visible area of the screen. The outer container is also set at a fixed value at the top of email messages minus the space occupied by the menu.

    The inner container occupies the width of the visible area multiplied by the number of articles. Articles also occupy a width in the viewport and shifted to the left. This allows you to organize them in a horizontal position, displaying one article at a time.

    Then you create a radio-element for each article, when the selector :checked is set in a certain radio-element, the inner container is shifted left or right by the number of “width crane” (vw) of each article. Adding a transition allows for the “sliding effect” while browsing articles:

    
    #navbox:checked ~ #a1radio:checked ~ .articles-cont .articles{  left:0px;}#navbox:checked ~ #a2radio:checked ~ .articles-cont .articles{  left:-100vw;}#navbox:checked ~ #a3radio:checked ~ .articles-cont .articles{  left:-200vw;}
    

    The value of vw does not work on Android, so you’ll have to arrange the articles one above the other and show the right, hiding or changing its z-index.

    Moving on articles

    To navigate through the articles, create labels of arrows, which will be activated by clicking the appropriate radio-element. These labels are hidden by default and displayed only a couple associated with the currently visible article.

    
    <style>#navbox:checked ~ #a1radio:checked ~ .toolbar-cont .a1nav,#navbox:checked ~ #a2radio:checked ~ .toolbar-cont .a2nav,#navbox:checked ~ #a3radio:checked ~ .toolbar-cont .a3nav{  display:block;}</style> <div class="nav-arrows a1nav">   <label> </label><label for="a2radio">»</label></div><div class="nav-arrows a2nav">   <label for="a1radio">«</label><label for="a3radio">»</label></div><div class="nav-arrows a3nav">   <label for="a2radio">«</label><label> </label></div>

    Index menu of articles

    Index menu contains a list of labels associated with articles in a hidden and absolutely positioned div, and is displayed when the user clicks on a menu, use the selector :hover.

    Interesting point, often if the menu is hidden right after selecting the element, the mail client just ignores the selection. To cope with this problem you can add the transition and delay.

    Code

    To work with the code of the example you can in the builder of one of the email services. In text form it is presented under the spoiler:

    The code of the example

    
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
    <meta name="viewport" content="width=device-width" />
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <style>
    * {
    margin:0;
    padding:0;
    font-family: "Helvetica Neue", "Helvetica", Helvetica, Arial, sans-serif;
    font-size: 100%;
    line-height: 1.5;
    color:#333333;
    }
    img{
    max-width:100%;
    }
    body {
    -webkit-text-size-adjust:none;
    width: 100%!important;
    height: 100%;
    }
    h1,h2{
    margin-bottom:15px;
    line-height: 1.3;
    font-weight:300;
    }
    h1 {
    font-size: 32px;
    }
    h2 {
    font-size: 22px;
    }
    .toolbar-cont{
    max-height:none!important;
    overflow:visible!important;
    z-index:10;
    width:100%;
    position:fixed;
    top:0px;
    left:0px;
    display:none;
    height:50px;
    background-color:#eeeeee;
    border-bottom:1px solid #222222;
    }
    .toolbar{
    height:50px;
    line-height:50px;
    display:block;
    text-decoration:none;
    }
    .toolbar-menu{
    z-index:10;
    text-align:center;
    position:absolute;
    top:51px;
    overflow:hidden;
    transition: all 0.3s;
    -webkit-transition: all 0.3s;
    transform: rotateX(90deg);
    -webkit-transform: rotateX(90deg);
    transform-origin: top;
    -webkit-transform-origin: top;
    -webkit-transition-delay: 0.5s;
    transition-delay: 0.5s;
    }
    .toolbar-menu label{
    display:block;
    padding:5px 20px 5px 20px;
    }
    .toolbar:hover + .toolbar-menu{
    display:block;
    transform: rotateX(0deg);
    -webkit-transform: rotateX(0deg);
    }
    .articles-cont{
    background-color:#ffffff;
    }
    
    #navbox:checked ~ .articles-cont{
    width:100%;
    height:100%;
    overflow:hidden;
    position:fixed;
    top:50px;
    left:0px;
    }
    #navbox:checked ~ .articles-cont .articles{
    position:absolute;
    left:0px;
    width:303vw;
    transition: all 0.3s;
    -webkit-transition: all 0.3s;
    height:100%;
    }
    #navbox:checked ~ .articles-cont .articles .art{
    width:100vw;
    float:left;
    height:1000px;
    overflow:hidden;
    }
    #navbox:checked ~ .articles-cont .articles .art div{
    width:90vw;
    padding:20px 5vw 10px 5vw;
    }
    input{
    max-height:0;
    display:none;
    }
    .nav-arrows{
    float:right;
    display:none;
    }
    .nav-arrows label{
    cursor:pointer;
    display:inline-block;
    vertical-align:middle;
    text-align:center;
    height:50px;
    width:50px;
    font-size:30px;
    font-weight:bold;
    }
    #navbox:checked ~ #a1radio:checked ~ .articles-cont .articles{
    left:0px;
    }
    #navbox:checked ~ #a2radio:checked ~ .articles-cont .articles{
    left:-100vw;
    }
    #navbox:checked ~ #a3radio:checked ~ .articles-cont .articles{
    left:-200vw;
    }
    #navbox:checked ~ #a1radio:checked ~ .articles-cont .a1,
    #navbox:checked ~ #a2radio:checked ~ .articles-cont .a2,
    #navbox:checked ~ #a3radio:checked ~ .articles-cont .a3{
    height:100%;
    overflow-y:scroll;
    }
    #navbox:checked ~ #a1radio:checked ~ .toolbar-cont .a1nav,
    #navbox:checked ~ #a2radio:checked ~ .toolbar-cont .a2nav,
    #navbox:checked ~ #a3radio:checked ~ .toolbar-cont .a3nav{
    display:block;
    }
    .closer{
    display:inline-block;
    vertical-align:middle;
    text-align:center;
    height:50px;
    width:50px;
    font-size:30px;
    font-weight:bold;
    float:left;
    }
    #navbox:checked ~ .opener{
    display:none;
    }
    #navbox:checked ~ .toolbar-cont{
    display:block!important;
    }
    
    @media screen and (max-width: 480px) {
    #cbox-capable:checked ~ .opener div{
    margin:10px auto;
    background-color:#1abc9c;
    color:#ffffff;
    border-radius:5px;
    display: block !important;
    max-height:50px !important;
    line-height:50px;
    text-align:center;
    vertical-align:middle;
    }
    }
    </style>
    </head>
    <body>
    <div id="main-cont" style="padding:20px;">
    <h1>FreshInbox</h1>
    <div style="dislay:block;width:350px;margin:0px auto;max-width:100%">
    <img src="http://placehold.it/350x150">
    </div>
    <!--[if !mso 9]><!-->
    <input id="cbox-capable" type="checkbox" style="display:none!important;max-height:0;visibility:hidden;" checked>
    <input id="navbox" type="checkbox" style="display:none!important;max-height:0;visibility:hidden;">
    <label for="navbox" class="opener">
    <div style="display:none;max-height:0px;overflow:hidden;cursor:pointer">Reader Mode</div></label>
    <input id="a1radio" name="qradio" type="radio" checked style="display:none!important;max-height:0;visibility:hidden;">
    <input id="a2radio" name="qradio" type="radio" style="display:none!important;max-height:0;visibility:hidden;">
    <input id="a3radio" name="qradio" type="radio" style="display:none!important;max-height:0;visibility:hidden;">
    
    <div class="toolbar-cont" style="display:none;max-height:0px;overflow:hidden;">
    <label for="navbox" class="closer">x</label>
    <div class="nav-arrows a1nav">
    <label> </label><label for="a2radio">»</label>
    </div>
    <div class="nav-arrows a2nav">
    <label for="a1radio">«</label><label for="a3radio">»</label>
    </div>
    <div class="nav-arrows a3nav">
    <label for="a2radio">«</label><label> </label>
    </div>
    
    <a href="#" class="toolbar">Article Index...</a>
    <div class="toolbar-menu" style="text-align:left;background-color:#C8DEFA;border:1px solid #888888;font-size:15px;">
    <label for="a1radio">Yahoo! Mail Fixes Media Query Bug. Yahoo!!!</label>
    <label for="a2radio">Outlook.com and Background Images</label>
    <label for="a3radio">Gmail iOS Increases Email Font Sizes – Again</label>
    </div>
    </div>
    <!--<![endif]-->
    
    <div class="articles-cont">
    <div class="articles">
    <div class="art a1"><div>
    <h2>Yahoo! Mail Fixes Media Query Bug. Yahoo!!!</h2>
    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
    
    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
    
    <HR>
    
    </div></div>
    <div class="art a2"><div>
    <h2>Outlook.com and Background Images</h2>
    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
    
    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
    
    <HR>
    
    </div></div>
    <div class="art a3"><div>
    <h2>Gmail iOS Increases Email Font Sizes – Again</h2>
    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
    
    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
    
    <HR>
    
    </div></div>
    </div>
    </div>
    </div>
    </body>
    </html>
    <b>
    

    This text is a translation of the article “Режим читателя: Пагинация в мобильных email-письмах”  published by @lol_wat on habrahabr.ru.

    About the CleanTalk service

    CleanTalk is a cloud service to protect websites from spam bots. CleanTalk uses protection methods that are invisible to the visitors of the website. This allows you to abandon the methods of protection that require the user to prove that he is a human (captcha, question-answer etc.).

  • WordCamp Europe in Vienna and the vector of development of WordPress

    WordCamp Europe in Vienna and the vector of development of WordPress

    This year the conference WordCamp Europe 2016 took place in Vienna and attracted more than 2300 guests. The capital of Austria is an excellent choice for such events, there are all conditions: convenient location, large meeting halls, and an active WordPress community. And there is something to see after the conference. Several of our developers have been on WordCamp Europe 2016. Under the cut – their story about the most interesting presentations and events.

    The format of the conference

    The conference lasted three days: the first two days we listened to the speeches, and the last day was given to the contributors. The reports were in different categories: Development, Design, Business, Content, Community, and took place in three streams, so everyone can find something interesting for yourself. Much attention speakers paid to high load questions, Continuous Integration, REST APIs, and the project Calypso.

    On the day of contributors signed up about 600 volunteers. On this day it was possible to take a direct part in the development of WordPress, to learn how to work the kernel developers, translators, as well as the team checking the plugins and themes to the official catalog. You can even get advice on the organization of WordPress community in your city.

    A nice bonus was the performance of Matt Mullenweg, the developer and the founder of WordPress, the founder of Automattic, WordPress.com, Akismet. But more on that below.

    The most interesting report

    PHP7 and WordPress

    The release of PHP7 could not remain unnoticed at WordCamp Europe: how to provide the work of WordPress on PHP7, said Dan Blows in his report What’s New in PHP7 and what to expect in PHP7.1.

    The core of WordPress and many plugins already support PHP7. Quoting the author, we can say: “Upgrade to PHP 7 easily, and probably everything will work immediately”. But he raised the points that should pay attention if you decided to migrate your website to PHP7.

    The speaker told about innovations in PHP and the benefits that you can get when going to the seventh version. Dan showed impressive statistics of speed up of work WordPress on PHP7 compared to PHP 5.6.

    A couple of reports about WordPress REST API

    Especially important were the reports about REST API. This is one of the most important and actively developing directions. News from the developers WordPress rest API, about the difficulties and decisions is incredibly valuable information. Thanks Joe Hoyle and Adam White! Look at their performances The Ultimate REST API talk and Using the REST API and JavaScript to create better WordPress interfaces.

    The reports disclosed the questions associated with use of the API and its development and expansion.

    Now REST API is not yet part of the core, it exists in the form of a plugin. Adam in his report underlines the benefits that will get WordPress with integration of REST in its core. However, we now have the opportunity to build our apps using the new API.

    The REST API gives unprecedented flexibility and expression “WordPress is limited only by your imagination” becomes a reality.

    Dashboard Calypso

    Due attention has been given to the relatively new development — Calypso. This is the administration panel of WordPress-sites, written in JS and running using WordPress REST API, which will definitely become popular.

    Designer Calypso told about the project in general, and about what it cost for the team this his development and shared approaches in organization effective communication in the project. As Davide Casali said: “Communication is the oxygen”. It is impossible not to agree.

    Experience of building a highly loaded WP-site

    WordPress has long been used for the development of high-load news portals. Such giants as TED, TechCrunch, CNN, NBC built their sites on it. Yes, to build a high-load website is not easy, but speakers from NewsCorp Australia told how to do everything correctly.

    Their experience – another precedent, proving the possibility of building on WP portals with millions of page views per day. Speakers gave valuable information about the development team and working process, talked about continuous integration, environment and visitor statistics. They also shared information that will help you to calculate the necessary costs for such a project.

    Incredibly useful report, including from the point of view of communication with clients: How NewsCorp Australia scaled WordPress to host Australias largest ‘news’ websites on WordPress VIP.

    About legacy-projects

    Andrew Nacin — Lead-developer of WordPress core. With years of experience in the development of such a popular CMS system, the kernel developers have identified and summarized the key points of the philosophy of WordPress, which adheres and Andrew.

    Get the big project “inherited” from people who have not really thought about the future is always difficult. And even painful. If you have such a project, the Andrew report will help to understand how to transform it in a stable and not require inappropriate investment product. Video of the report is available at the link.

    Elasticsearch and ElasticPress

    Full text search for MySQL databases by itself is not the best solution. But on high load sites and sites with large volumes of data — even more so. Elasticsearch is one of the solutions to implement an efficient search. How it works, how to configure Elasticsearch, how to protect data, and finally how to use it in your projects? These questions are answered by Taylor Lovett in the report Modernizing WordPress Search with Elasticsearch.

    Taylor also tells about the plugin ElasticPress. The speaker is one of the developers of this plugin and knows what he’s talking about. In general, meetings with the developers of the components is always a unique opportunity to get information about the details of the use and future development plans.

    The report about security

    Of course, the most popular platform for developing websites in the world is one of the most attacked. So you need to constantly pay attention to the issue of information security.

    Maurizio Pelizzone gave a presentation about securing WordPress websites: WordPress Hardening – Ten tips in ten minutes. The lecturer gave useful tips on how to reduce the risk to be hacked and sleep well.

    Copywriting for professionals

    At the end of the first day of the conference was the author of the best SEO-plugin for WordPress Joost de Valk and his wife Marieke van de Rakt. The report Beyond SEO – Copywriting for professionals, they told about the next stage in the evolution of search engines and the importance of high-quality texts.

    Speakers against the “scorched earth tactics”. Joost and Marieke prefer sustainable and holistic approach to SEO, which involves focusing on all areas of optimization:

    • The technical quality.
    • Good UX & UI.
    • Impeccable security.
    • Great PR & Social

    The basis of this approach is the high-quality content. And the principles of such content were presented in the report. In addition, the speakers spoke about a new functionality of their plugin, which allows you to make recommendations for improvement of the texts on your website.

    Interview with Matt Mullenweg

    Special attention deserves an interview with Matt Mullenweg: Interview and Q&A. the speech of Matt is a traditional part of WordCamp Europe. Right on the stage there is a sofa and provided almost homely atmosphere. In the second part of the perfomance, Matt talked to the audience.

    They discussed potentially leading role REST API and interfaces on  JS. Talked about the most successful and promising projects: Jetpack, WooCommerce and WordPress.com that do a lot for the success of WordPress in particular, and for an open Internet in general. Remembered about competitors, but Matt doesn’t consider them dangerous.

    And much more

    There were other interesting presentations, which we did not visit because we could not be simultaneously on all three streams. A complete list of video, as always, loaded on wordpress.tv.

    Day contributors, how to develop core of WP

    The conference was not limited by two days, full of interesting presentations and communication. For special interested was scheduled Contributor Day, which signed up about 600 people. It was held at the University of Vienna, Faculty of Informatics.

    Each of the participants chose the direction in which he can get acquainted with the process of open-source development and to assist in the development of WordPress. Among the areas were: the development of the core, development of plugins and themes, internationalization, design, marketing, and support. Each group was coordinated by an experienced supervisor. The motto for the day was “Thank WordPress”. You could join the community, gain new experience, improve your professional level and make WordPress better.

    The future of WordPress

    WordPress is actively developed. The most interesting and promising areas — REST API and JavaScript interfaces. And the last were possible thanks to partly all the same REST API.

    A lot of improvements in the core, for example, in recent releases significantly improved internationalization. Technology stack, development approaches, tools, and more — all have changed greatly since the advent of the first version of WordPress. There is movement forward, we are seeing regular releases that add something new.

    Good news is that the core already supports PHP7. We already develop projects at NIX Solutions on a fresh PHP. But as for a full transition to the seventh version, here the prospect is not very encouraging. The fact that plugins and themes are supported by the community and by individual companies and not all of them in a hurry to implement support for PHP7.

    What’s more surprising at the conference in Vienna is the maturity of the European community and a serious attitude to WP. We are sure that with such a large, active and talented community, WordPress has a great future.

    Next WCEU 2017 in Paris

    At the end of the conference, according to tradition, was announced the next city for WordCamp Europe, it became the capital of France. See you in Paris!

    This text is a translation of the article “WordCamp Europe в Вене и вектор развития WordPress”  published by @NIX_Solutions on habrahabr.ru.

    About the CleanTalk service

    CleanTalk is a cloud service to protect websites from spam bots. CleanTalk uses protection methods that are invisible to the visitors of the website. This allows you to abandon the methods of protection that require the user to prove that he is a human (captcha, question-answer etc.).

  • “Write letters”: Three techniques of a good layout of emails

    “Write letters”: Three techniques of a good layout of emails

    To the layout of letters and mailings devoted to a huge amount of tutorials. In this volume of information is very easy to get lost, and to write letters and do mailings still need. So today we have prepared material, which was collected three popular techniques for effective layout of emails, suitable for beginner web designers.

    Interactive writing

    Interactive elements dilute the monotonous text and save the reader’s time, and therefore are easy tool for creating sales letters and beautifully designed texts.

    As an example, let’s look at a simple way of creating interactive images. It consists of three steps:

    1. Create a table of one cell and set an background image that is displayed immediately after page loads.

    <table cellpadding=0 cellspacing=0 border=0><tr>
    <td width=240 background="http://.../alternate-image.jpg">
    </td></tr></table>

    2. Set the main image and “hide” it in a link with the class img-swap. This will create a hover-effect: when you hover over the background image, the main image will be in its place.

    <table cellpadding=0 cellspacing=0 border=0><tr><td width=240 background="http://../alternate-image.jpg"><a class="img-swap" href="http://../link"><img src="http://../primary-image.jpg" width="240" height="170" border="0" style="display:block;" alt="the product"></a></td></tr></table>
    

    3. Set up a command :hover and set the styles for the class img-swap.

    <style>.img-swap {  display: block;  width: 240px;  height: 170px;} .img-swap:hover img {  height: 0px;}</style>

    This version of the creation of interactive images is supported by services like: Mail, Outlook, Yahoo! and Gmail (with modifications).

    Progressive enhancement

    Progressive enhancement is a strategy involving the gradual creation of web pages – from simple to complex. First is the structure of the letter, and then to work on improving the appearance and usability.

    First, the content of email is marked up using HTML to form the structure, to build the layout. After that comes the debugging of the design by tools of CSS – sets the CSS styles improve the design and presentation of the document – here you can set background image, set font options, and so on. In the third stage apply the new capabilities of CSS3. After marking the content, and bring it in order, comes time of JavaScript that is responsible for communication with the interface and dynamic elements.

    Step-by-step work with a document allows you to track bugs and fix them on the spot, because the appearance of a single defect can affect the result of all the work. If you want to look at progressive enhancement in action, then pay attention to the example from html academy.

    Media queries

    Media query is the component of the CSS language, allowing you to select different sets of CSS styles. Sets of styles – the key to creating an attractive appearance of the document (illustrative practical example of CSS in action you will find the link).

    A media query consists of three sequential components that are configured step by step:

    • Media type – identifies the environment the application of the rules. There are such types, as all, print, screen (used for email) and speech
    • Expressions is a list of device properties describing, for example, the width and height  of the screen, the color
    • Rules of styles are used when you open a message in an environment appropriate to the type and properties in the expression

    Media queries are indispensable for optimizing the display format of emails on mobile devices. They allow you to move from a fixed design to a “floating” – the document will look good on different platforms.

    Moreover, the technology of media queries can be used for targeting of services (selection services that meet the specified criteria) and adapting to them. By analogy devices are targeted, where it is important to take into account the size of the screen. For example, the standard code for the iPhone 6 Plus is as follows:

    @media screen and (max-device-width: 414px) and (max-device-height: 776px) {    /* Insert styles here */
    

    Media queries allow you to create beautiful and, most importantly, adaptive emails that look good on any device, but you need to be prepared for the fact that many email clients do not support this technology.

    Interactive writing, progressive enhancement and media queries – it’s quite common techniques that can turn your electronic message into small works of art, moreover, they are a good basis for further development of your layout skills.

    This text is a translation of the article “«Пишите письма»: Три техники верстки хороших email’ов”  published by @mailman on habrahabr.ru.

    About the CleanTalk service

    CleanTalk is a cloud service to protect websites from spam bots. CleanTalk uses protection methods that are invisible to the visitors of the website. This allows you to abandon the methods of protection that require the user to prove that he is a human (captcha, question-answer etc.).