mirror of
https://github.com/jhillyerd/inbucket.git
synced 2025-12-17 09:37:02 +00:00
sanitize: naive CSS sanitizer implementation
- CSS sanitizer allows a limited set of properties in a style attribute. - Added a CSS inlined version of the tutsplus responsive test mail. - Linter fixes in inbucket.go
This commit is contained in:
30
CHANGELOG.md
30
CHANGELOG.md
@@ -4,8 +4,16 @@ Change Log
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
This project adheres to [Semantic Versioning](http://semver.org/).
|
This project adheres to [Semantic Versioning](http://semver.org/).
|
||||||
|
|
||||||
[1.2.0-rc2] - 2017-12-15
|
## [Unreleased]
|
||||||
------------------------
|
|
||||||
|
### Added
|
||||||
|
- Button to purge mailbox contents from the UI.
|
||||||
|
- Simple HTML/CSS sanitization; `Safe HTML` and `Plain Text` UI tabs.
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- Reverse message display sort order in the UI; now newest first.
|
||||||
|
|
||||||
|
## [1.2.0-rc2] - 2017-12-15
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
- `rest/client` types `MessageHeader` and `Message` with convenience methods;
|
- `rest/client` types `MessageHeader` and `Message` with convenience methods;
|
||||||
@@ -20,8 +28,7 @@ This project adheres to [Semantic Versioning](http://semver.org/).
|
|||||||
types
|
types
|
||||||
- Fixed panic when `monitor.history` set to 0
|
- Fixed panic when `monitor.history` set to 0
|
||||||
|
|
||||||
[1.2.0-rc1] - 2017-01-29
|
## [1.2.0-rc1] - 2017-01-29
|
||||||
------------------------
|
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
- Storage of `To:` header in messages (likely breaks existing datastores)
|
- Storage of `To:` header in messages (likely breaks existing datastores)
|
||||||
@@ -47,8 +54,7 @@ This project adheres to [Semantic Versioning](http://semver.org/).
|
|||||||
- Allow increased local-part length of 128 chars for Mailgun
|
- Allow increased local-part length of 128 chars for Mailgun
|
||||||
- RedHat and Ubuntu now use systemd instead of legacy init systems
|
- RedHat and Ubuntu now use systemd instead of legacy init systems
|
||||||
|
|
||||||
[1.1.0] - 2016-09-03
|
## [1.1.0] - 2016-09-03
|
||||||
--------------------
|
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
- Homebrew inbucket.conf and formula (see README)
|
- Homebrew inbucket.conf and formula (see README)
|
||||||
@@ -56,8 +62,7 @@ This project adheres to [Semantic Versioning](http://semver.org/).
|
|||||||
### Fixed
|
### Fixed
|
||||||
- Log and continue when unable to delete oldest message during cap enforcement
|
- Log and continue when unable to delete oldest message during cap enforcement
|
||||||
|
|
||||||
[1.1.0-rc2] - 2016-03-06
|
## [1.1.0-rc2] - 2016-03-06
|
||||||
------------------------
|
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
- Message Cap to status page
|
- Message Cap to status page
|
||||||
@@ -67,8 +72,7 @@ This project adheres to [Semantic Versioning](http://semver.org/).
|
|||||||
- Shutdown hang in retention scanner
|
- Shutdown hang in retention scanner
|
||||||
- Display empty subject as `(No Subject)`
|
- Display empty subject as `(No Subject)`
|
||||||
|
|
||||||
[1.1.0-rc1] - 2016-03-04
|
## [1.1.0-rc1] - 2016-03-04
|
||||||
------------------------
|
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
- Inbucket now builds with Go 1.5 or 1.6
|
- Inbucket now builds with Go 1.5 or 1.6
|
||||||
@@ -82,8 +86,7 @@ This project adheres to [Semantic Versioning](http://semver.org/).
|
|||||||
- RESTful API moved to `/api/v1` base URI
|
- RESTful API moved to `/api/v1` base URI
|
||||||
- More graceful shutdown on Ctrl-C or when errors encountered
|
- More graceful shutdown on Ctrl-C or when errors encountered
|
||||||
|
|
||||||
[1.0] - 2014-04-14
|
## [1.0] - 2014-04-14
|
||||||
------------------
|
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
- Add new configuration option `mailbox.message.cap` to prevent individual
|
- Add new configuration option `mailbox.message.cap` to prevent individual
|
||||||
@@ -100,8 +103,7 @@ This project adheres to [Semantic Versioning](http://semver.org/).
|
|||||||
[1.0]: https://github.com/jhillyerd/inbucket/compare/1.0-rc1...1.0
|
[1.0]: https://github.com/jhillyerd/inbucket/compare/1.0-rc1...1.0
|
||||||
|
|
||||||
|
|
||||||
Release Checklist
|
## Release Checklist
|
||||||
-----------------
|
|
||||||
|
|
||||||
1. Create release branch: `git flow release start 1.x.0`
|
1. Create release branch: `git flow release start 1.x.0`
|
||||||
2. Update CHANGELOG.md:
|
2. Update CHANGELOG.md:
|
||||||
|
|||||||
@@ -86,7 +86,7 @@ func main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Setup signal handler
|
// Setup signal handler
|
||||||
sigChan := make(chan os.Signal)
|
sigChan := make(chan os.Signal, 1)
|
||||||
signal.Notify(sigChan, syscall.SIGHUP, syscall.SIGTERM, syscall.SIGINT)
|
signal.Notify(sigChan, syscall.SIGHUP, syscall.SIGTERM, syscall.SIGINT)
|
||||||
|
|
||||||
// Initialize logging
|
// Initialize logging
|
||||||
@@ -150,7 +150,7 @@ signalLoop:
|
|||||||
log.Infof("Received SIGTERM, shutting down")
|
log.Infof("Received SIGTERM, shutting down")
|
||||||
close(shutdownChan)
|
close(shutdownChan)
|
||||||
}
|
}
|
||||||
case _ = <-shutdownChan:
|
case <-shutdownChan:
|
||||||
rootCancel()
|
rootCancel()
|
||||||
break signalLoop
|
break signalLoop
|
||||||
}
|
}
|
||||||
|
|||||||
110
sanitize/css.go
Normal file
110
sanitize/css.go
Normal file
@@ -0,0 +1,110 @@
|
|||||||
|
package sanitize
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/gorilla/css/scanner"
|
||||||
|
)
|
||||||
|
|
||||||
|
// propertyRule may someday allow control of what values are valid for a particular property.
|
||||||
|
type propertyRule struct{}
|
||||||
|
|
||||||
|
var allowedProperties = map[string]propertyRule{
|
||||||
|
"align": {},
|
||||||
|
"background-color": {},
|
||||||
|
"border": {},
|
||||||
|
"border-bottom": {},
|
||||||
|
"border-left": {},
|
||||||
|
"border-radius": {},
|
||||||
|
"border-right": {},
|
||||||
|
"border-top": {},
|
||||||
|
"box-sizing": {},
|
||||||
|
"clear": {},
|
||||||
|
"color": {},
|
||||||
|
"content": {},
|
||||||
|
"display": {},
|
||||||
|
"font-family": {},
|
||||||
|
"font-size": {},
|
||||||
|
"font-weight": {},
|
||||||
|
"height": {},
|
||||||
|
"line-height": {},
|
||||||
|
"margin": {},
|
||||||
|
"margin-bottom": {},
|
||||||
|
"margin-left": {},
|
||||||
|
"margin-right": {},
|
||||||
|
"margin-top": {},
|
||||||
|
"max-height": {},
|
||||||
|
"max-width": {},
|
||||||
|
"overflow": {},
|
||||||
|
"padding": {},
|
||||||
|
"padding-bottom": {},
|
||||||
|
"padding-left": {},
|
||||||
|
"padding-right": {},
|
||||||
|
"padding-top": {},
|
||||||
|
"table-layout": {},
|
||||||
|
"text-align": {},
|
||||||
|
"text-decoration": {},
|
||||||
|
"text-shadow": {},
|
||||||
|
"vertical-align": {},
|
||||||
|
"width": {},
|
||||||
|
"word-break": {},
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handler Token, return next state.
|
||||||
|
type stateHandler func(b *bytes.Buffer, t *scanner.Token) stateHandler
|
||||||
|
|
||||||
|
func sanitizeStyle(input string) string {
|
||||||
|
b := &bytes.Buffer{}
|
||||||
|
scan := scanner.New(input)
|
||||||
|
state := stateStart
|
||||||
|
for {
|
||||||
|
t := scan.Next()
|
||||||
|
if t.Type == scanner.TokenEOF {
|
||||||
|
return b.String()
|
||||||
|
}
|
||||||
|
if t.Type == scanner.TokenError {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
state = state(b, t)
|
||||||
|
if state == nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func stateStart(b *bytes.Buffer, t *scanner.Token) stateHandler {
|
||||||
|
switch t.Type {
|
||||||
|
case scanner.TokenIdent:
|
||||||
|
_, ok := allowedProperties[strings.ToLower(t.Value)]
|
||||||
|
if !ok {
|
||||||
|
return stateEat
|
||||||
|
}
|
||||||
|
b.WriteString(t.Value)
|
||||||
|
return stateValid
|
||||||
|
case scanner.TokenS:
|
||||||
|
return stateStart
|
||||||
|
}
|
||||||
|
// Unexpected type.
|
||||||
|
b.WriteString("/*" + t.Type.String() + "*/")
|
||||||
|
return stateEat
|
||||||
|
}
|
||||||
|
|
||||||
|
func stateEat(b *bytes.Buffer, t *scanner.Token) stateHandler {
|
||||||
|
if t.Type == scanner.TokenChar && t.Value == ";" {
|
||||||
|
// Done eating.
|
||||||
|
return stateStart
|
||||||
|
}
|
||||||
|
// Throw away this token.
|
||||||
|
return stateEat
|
||||||
|
}
|
||||||
|
|
||||||
|
func stateValid(b *bytes.Buffer, t *scanner.Token) stateHandler {
|
||||||
|
state := stateValid
|
||||||
|
if t.Type == scanner.TokenChar && t.Value == ";" {
|
||||||
|
// End of property.
|
||||||
|
state = stateStart
|
||||||
|
}
|
||||||
|
b.WriteString(t.Value)
|
||||||
|
return state
|
||||||
|
}
|
||||||
34
sanitize/css_test.go
Normal file
34
sanitize/css_test.go
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
package sanitize
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestSanitizeStyle(t *testing.T) {
|
||||||
|
testCases := []struct {
|
||||||
|
input, want string
|
||||||
|
}{
|
||||||
|
{"", ""},
|
||||||
|
{
|
||||||
|
"color: red;",
|
||||||
|
"color: red;",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"background-color: black; color: white",
|
||||||
|
"background-color: black;color: white",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"background-color: black; invalid: true; color: white",
|
||||||
|
"background-color: black;color: white",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tc := range testCases {
|
||||||
|
t.Run(tc.input, func(t *testing.T) {
|
||||||
|
got := sanitizeStyle(tc.input)
|
||||||
|
if got != tc.want {
|
||||||
|
t.Errorf("got: %q, want: %q, input: %q", got, tc.want, tc.input)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,9 +1,88 @@
|
|||||||
package sanitize
|
package sanitize
|
||||||
|
|
||||||
import "github.com/microcosm-cc/bluemonday"
|
import (
|
||||||
|
"bufio"
|
||||||
|
"bytes"
|
||||||
|
"io"
|
||||||
|
"regexp"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/microcosm-cc/bluemonday"
|
||||||
|
"golang.org/x/net/html"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
cssSafe = regexp.MustCompile(".*")
|
||||||
|
policy = bluemonday.UGCPolicy().
|
||||||
|
AllowElements("center").
|
||||||
|
AllowAttrs("style").Matching(cssSafe).Globally()
|
||||||
|
)
|
||||||
|
|
||||||
func HTML(html string) (output string, err error) {
|
func HTML(html string) (output string, err error) {
|
||||||
policy := bluemonday.UGCPolicy()
|
output, err = sanitizeStyleTags(html)
|
||||||
output = policy.Sanitize(html)
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
output = policy.Sanitize(output)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func sanitizeStyleTags(input string) (string, error) {
|
||||||
|
r := strings.NewReader(input)
|
||||||
|
b := &bytes.Buffer{}
|
||||||
|
if err := styleTagFilter(b, r); err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return b.String(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func styleTagFilter(w io.Writer, r io.Reader) error {
|
||||||
|
bw := bufio.NewWriter(w)
|
||||||
|
b := make([]byte, 256)
|
||||||
|
z := html.NewTokenizer(r)
|
||||||
|
for {
|
||||||
|
b = b[:0]
|
||||||
|
tt := z.Next()
|
||||||
|
switch tt {
|
||||||
|
case html.ErrorToken:
|
||||||
|
err := z.Err()
|
||||||
|
if err == io.EOF {
|
||||||
|
return bw.Flush()
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
case html.StartTagToken, html.SelfClosingTagToken:
|
||||||
|
name, hasAttr := z.TagName()
|
||||||
|
if !hasAttr {
|
||||||
|
bw.Write(z.Raw())
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
b = append(b, '<')
|
||||||
|
b = append(b, name...)
|
||||||
|
for {
|
||||||
|
key, val, more := z.TagAttr()
|
||||||
|
strval := string(val)
|
||||||
|
style := false
|
||||||
|
if strings.ToLower(string(key)) == "style" {
|
||||||
|
style = true
|
||||||
|
strval = sanitizeStyle(strval)
|
||||||
|
}
|
||||||
|
if !style || strval != "" {
|
||||||
|
b = append(b, ' ')
|
||||||
|
b = append(b, key...)
|
||||||
|
b = append(b, '=', '"')
|
||||||
|
b = append(b, []byte(html.EscapeString(strval))...)
|
||||||
|
b = append(b, '"')
|
||||||
|
}
|
||||||
|
if !more {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if tt == html.SelfClosingTagToken {
|
||||||
|
b = append(b, '/')
|
||||||
|
}
|
||||||
|
bw.Write(append(b, '>'))
|
||||||
|
default:
|
||||||
|
bw.Write(z.Raw())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ func TestHTMLSimpleFormatting(t *testing.T) {
|
|||||||
"<em>emphasis</em>",
|
"<em>emphasis</em>",
|
||||||
"<strong>strong</strong>",
|
"<strong>strong</strong>",
|
||||||
"<div><span>text</span></div>",
|
"<div><span>text</span></div>",
|
||||||
|
"<center>text</center>",
|
||||||
}
|
}
|
||||||
for _, ts := range testStrings {
|
for _, ts := range testStrings {
|
||||||
t.Run(ts, func(t *testing.T) {
|
t.Run(ts, func(t *testing.T) {
|
||||||
@@ -75,3 +76,96 @@ func TestHTMLScriptTags(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestSanitizeStyleTags(t *testing.T) {
|
||||||
|
testCases := []struct {
|
||||||
|
name, input, want string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
"empty",
|
||||||
|
``,
|
||||||
|
``,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"open",
|
||||||
|
`<div>`,
|
||||||
|
`<div>`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"open close",
|
||||||
|
`<div></div>`,
|
||||||
|
`<div></div>`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"inner text",
|
||||||
|
`<div>foo bar</div>`,
|
||||||
|
`<div>foo bar</div>`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"self close",
|
||||||
|
`<br/>`,
|
||||||
|
`<br/>`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"open params",
|
||||||
|
`<div id="me">`,
|
||||||
|
`<div id="me">`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"open params squote",
|
||||||
|
`<div id="me" title='best'>`,
|
||||||
|
`<div id="me" title="best">`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"open style",
|
||||||
|
`<div id="me" style="color: red;">`,
|
||||||
|
`<div id="me" style="color: red;">`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"open style squote",
|
||||||
|
`<div id="me" style='color: red;'>`,
|
||||||
|
`<div id="me" style="color: red;">`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"open style mixed case",
|
||||||
|
`<div id="me" StYlE="color: red;">`,
|
||||||
|
`<div id="me" style="color: red;">`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"closed style",
|
||||||
|
`<br style="border: 1px solid red;"/>`,
|
||||||
|
`<br style="border: 1px solid red;"/>`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"mixed case style",
|
||||||
|
`<br StYlE="border: 1px solid red;"/>`,
|
||||||
|
`<br style="border: 1px solid red;"/>`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"mixed case invalid style",
|
||||||
|
`<br StYlE="position: fixed;"/>`,
|
||||||
|
`<br/>`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"mixed",
|
||||||
|
`<p id='i' title="cla'zz" style="font-size: 25px;"><b>some text</b></p>`,
|
||||||
|
`<p id="i" title="cla'zz" style="font-size: 25px;"><b>some text</b></p>`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"invalid styles",
|
||||||
|
`<div id="me" style='position: absolute;'>`,
|
||||||
|
`<div id="me">`,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tc := range testCases {
|
||||||
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
|
got, err := sanitize.HTML(tc.input)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if got != tc.want {
|
||||||
|
t.Errorf("input: %s\ngot : %s\nwant: %s", tc.input, got, tc.want)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
393
swaks-tests/nonmime-html-inlined.raw
Normal file
393
swaks-tests/nonmime-html-inlined.raw
Normal file
@@ -0,0 +1,393 @@
|
|||||||
|
Date: %DATE%
|
||||||
|
To: %TO_ADDRESS%
|
||||||
|
From: %FROM_ADDRESS%
|
||||||
|
Subject: tutsplus responsive inlined CSS
|
||||||
|
MIME-Version: 1.0
|
||||||
|
Content-Type: text/html; charset="UTF-8"
|
||||||
|
|
||||||
|
<!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 http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||||
|
<!--[if !mso]><!-->
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||||
|
<!--<![endif]-->
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<title></title>
|
||||||
|
<!--[if (gte mso 9)|(IE)]>
|
||||||
|
<style type="text/css">
|
||||||
|
table {border-collapse: collapse !important;}
|
||||||
|
</style>
|
||||||
|
<![endif]-->
|
||||||
|
</head>
|
||||||
|
<body style="margin-top:0 !important;margin-bottom:0 !important;margin-right:0 !important;margin-left:0 !important;padding-top:0;padding-bottom:0;padding-right:0;padding-left:0;background-color:#ffffff;" >
|
||||||
|
<center class="wrapper" style="width:100%;table-layout:fixed;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%;" >
|
||||||
|
<div class="webkit" style="max-width:600px;margin-top:0;margin-bottom:0;margin-right:auto;margin-left:auto;" >
|
||||||
|
<!--[if (gte mso 9)|(IE)]>
|
||||||
|
<table width="600" align="center" style="border-spacing:0;font-family:sans-serif;color:#333333;" >
|
||||||
|
<tr>
|
||||||
|
<td style="padding-top:0;padding-bottom:0;padding-right:0;padding-left:0;" >
|
||||||
|
<![endif]-->
|
||||||
|
<table class="outer" align="center" style="border-spacing:0;font-family:sans-serif;color:#333333;Margin:0 auto;width:100%;max-width:600px;" >
|
||||||
|
<tr>
|
||||||
|
<td class="full-width-image" style="padding-top:0;padding-bottom:0;padding-right:0;padding-left:0;" >
|
||||||
|
<img src="http://www.inbucket.org/email-assets/responsive/header.jpg" width="600" alt="" style="border-width:0;width:100%;max-width:600px;height:auto;" />
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="one-column" style="padding-top:0;padding-bottom:0;padding-right:0;padding-left:0;" >
|
||||||
|
<table width="100%" style="border-spacing:0;font-family:sans-serif;color:#333333;" >
|
||||||
|
<tr>
|
||||||
|
<td class="inner contents" style="padding-top:10px;padding-bottom:10px;padding-right:10px;padding-left:10px;width:100%;text-align:left;" >
|
||||||
|
<p class="h1" style="Margin:0;font-weight:bold;font-size:14px;Margin-bottom:10px;" >Lorem ipsum dolor sit amet</p>
|
||||||
|
<p style="Margin:0;font-size:14px;Margin-bottom:10px;" >
|
||||||
|
Compare to:
|
||||||
|
<a href="http://tutsplus.github.io/creating-a-future-proof-responsive-email-without-media-queries/index.html" style="color:#ee6a56;text-decoration:underline;" >
|
||||||
|
tutsplus sample</a>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p style="Margin:0;font-size:14px;Margin-bottom:10px;" >Copyright (c) 2015, Envato Tuts+<br/>
|
||||||
|
All rights reserved.</p>
|
||||||
|
|
||||||
|
<p style="Margin:0;font-size:14px;Margin-bottom:10px;" >Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:</p>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li>Redistributions of source code must retain the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer.</li>
|
||||||
|
|
||||||
|
<li>Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer in the documentation
|
||||||
|
and/or other materials provided with the distribution.</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<p style="Margin:0;font-size:14px;Margin-bottom:10px;" >THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
|
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
|
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
|
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="two-column" style="padding-top:0;padding-bottom:0;padding-right:0;padding-left:0;text-align:center;font-size:0;" >
|
||||||
|
<!--[if (gte mso 9)|(IE)]>
|
||||||
|
<table width="100%" style="border-spacing:0;font-family:sans-serif;color:#333333;" >
|
||||||
|
<tr>
|
||||||
|
<td width="50%" valign="top" style="padding-top:0;padding-bottom:0;padding-right:0;padding-left:0;" >
|
||||||
|
<![endif]-->
|
||||||
|
<div class="column" style="width:100%;max-width:300px;display:inline-block;vertical-align:top;" >
|
||||||
|
<table width="100%" style="border-spacing:0;font-family:sans-serif;color:#333333;" >
|
||||||
|
<tr>
|
||||||
|
<td class="inner" style="padding-top:10px;padding-bottom:10px;padding-right:10px;padding-left:10px;" >
|
||||||
|
<table class="contents" style="border-spacing:0;font-family:sans-serif;color:#333333;width:100%;font-size:14px;text-align:left;" >
|
||||||
|
<tr>
|
||||||
|
<td style="padding-top:0;padding-bottom:0;padding-right:0;padding-left:0;" >
|
||||||
|
<img src="http://www.inbucket.org/email-assets/responsive/two-column-01.jpg" width="280" alt="" style="border-width:0;width:100%;max-width:280px;height:auto;" />
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="text" style="padding-bottom:0;padding-right:0;padding-left:0;padding-top:10px;" >
|
||||||
|
Maecenas sed ante pellentesque, posuere leo id, eleifend dolor. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos.
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<!--[if (gte mso 9)|(IE)]>
|
||||||
|
</td><td width="50%" valign="top" style="padding-top:0;padding-bottom:0;padding-right:0;padding-left:0;" >
|
||||||
|
<![endif]-->
|
||||||
|
<div class="column" style="width:100%;max-width:300px;display:inline-block;vertical-align:top;" >
|
||||||
|
<table width="100%" style="border-spacing:0;font-family:sans-serif;color:#333333;" >
|
||||||
|
<tr>
|
||||||
|
<td class="inner" style="padding-top:10px;padding-bottom:10px;padding-right:10px;padding-left:10px;" >
|
||||||
|
<table class="contents" style="border-spacing:0;font-family:sans-serif;color:#333333;width:100%;font-size:14px;text-align:left;" >
|
||||||
|
<tr>
|
||||||
|
<td style="padding-top:0;padding-bottom:0;padding-right:0;padding-left:0;" >
|
||||||
|
<img src="http://www.inbucket.org/email-assets/responsive/two-column-02.jpg" width="280" alt="" style="border-width:0;width:100%;max-width:280px;height:auto;" />
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="text" style="padding-bottom:0;padding-right:0;padding-left:0;padding-top:10px;" >
|
||||||
|
Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Maecenas sed ante pellentesque, posuere leo id, eleifend dolor.
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<!--[if (gte mso 9)|(IE)]>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<![endif]-->
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="three-column" style="padding-right:0;padding-left:0;text-align:center;font-size:0;padding-top:10px;padding-bottom:10px;" >
|
||||||
|
<!--[if (gte mso 9)|(IE)]>
|
||||||
|
<table width="100%" style="border-spacing:0;font-family:sans-serif;color:#333333;" >
|
||||||
|
<tr>
|
||||||
|
<td width="200" valign="top" style="padding-top:0;padding-bottom:0;padding-right:0;padding-left:0;" >
|
||||||
|
<![endif]-->
|
||||||
|
<div class="column" style="width:100%;max-width:200px;display:inline-block;vertical-align:top;" >
|
||||||
|
<table width="100%" style="border-spacing:0;font-family:sans-serif;color:#333333;" >
|
||||||
|
<tr>
|
||||||
|
<td class="inner" style="padding-top:10px;padding-bottom:10px;padding-right:10px;padding-left:10px;" >
|
||||||
|
<table class="contents" style="border-spacing:0;font-family:sans-serif;color:#333333;width:100%;font-size:14px;text-align:center;" >
|
||||||
|
<tr>
|
||||||
|
<td style="padding-top:0;padding-bottom:0;padding-right:0;padding-left:0;" >
|
||||||
|
<img src="http://www.inbucket.org/email-assets/responsive/three-column-01.jpg" width="180" alt="" style="border-width:0;width:100%;max-width:180px;height:auto;" />
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="text" style="padding-bottom:0;padding-right:0;padding-left:0;padding-top:10px;" >
|
||||||
|
Scelerisque congue eros eu posuere. Praesent in felis ut velit pretium lobortis rhoncus ut erat.
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<!--[if (gte mso 9)|(IE)]>
|
||||||
|
</td><td width="200" valign="top" style="padding-top:0;padding-bottom:0;padding-right:0;padding-left:0;" >
|
||||||
|
<![endif]-->
|
||||||
|
<div class="column" style="width:100%;max-width:200px;display:inline-block;vertical-align:top;" >
|
||||||
|
<table width="100%" style="border-spacing:0;font-family:sans-serif;color:#333333;" >
|
||||||
|
<tr>
|
||||||
|
<td class="inner" style="padding-top:10px;padding-bottom:10px;padding-right:10px;padding-left:10px;" >
|
||||||
|
<table class="contents" style="border-spacing:0;font-family:sans-serif;color:#333333;width:100%;font-size:14px;text-align:center;" >
|
||||||
|
<tr>
|
||||||
|
<td style="padding-top:0;padding-bottom:0;padding-right:0;padding-left:0;" >
|
||||||
|
<img src="http://www.inbucket.org/email-assets/responsive/three-column-02.jpg" width="180" alt="" style="border-width:0;width:100%;max-width:180px;height:auto;" />
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="text" style="padding-bottom:0;padding-right:0;padding-left:0;padding-top:10px;" >
|
||||||
|
Maecenas sed ante pellentesque, posuere leo id, eleifend dolor.
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<!--[if (gte mso 9)|(IE)]>
|
||||||
|
</td><td width="200" valign="top" style="padding-top:0;padding-bottom:0;padding-right:0;padding-left:0;" >
|
||||||
|
<![endif]-->
|
||||||
|
<div class="column" style="width:100%;max-width:200px;display:inline-block;vertical-align:top;" >
|
||||||
|
<table width="100%" style="border-spacing:0;font-family:sans-serif;color:#333333;" >
|
||||||
|
<tr>
|
||||||
|
<td class="inner" style="padding-top:10px;padding-bottom:10px;padding-right:10px;padding-left:10px;" >
|
||||||
|
<table class="contents" style="border-spacing:0;font-family:sans-serif;color:#333333;width:100%;font-size:14px;text-align:center;" >
|
||||||
|
<tr>
|
||||||
|
<td style="padding-top:0;padding-bottom:0;padding-right:0;padding-left:0;" >
|
||||||
|
<img src="http://www.inbucket.org/email-assets/responsive/three-column-03.jpg" width="180" alt="" style="border-width:0;width:100%;max-width:180px;height:auto;" />
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="text" style="padding-bottom:0;padding-right:0;padding-left:0;padding-top:10px;" >
|
||||||
|
Praesent laoreet malesuada cursus. Maecenas scelerisque congue eros eu posuere.
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<!--[if (gte mso 9)|(IE)]>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<![endif]-->
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="three-column" style="padding-right:0;padding-left:0;text-align:center;font-size:0;padding-top:10px;padding-bottom:10px;" >
|
||||||
|
<!--[if (gte mso 9)|(IE)]>
|
||||||
|
<table width="100%" style="border-spacing:0;font-family:sans-serif;color:#333333;" >
|
||||||
|
<tr>
|
||||||
|
<td width="200" valign="top" style="padding-top:0;padding-bottom:0;padding-right:0;padding-left:0;" >
|
||||||
|
<![endif]-->
|
||||||
|
<div class="column" style="width:100%;max-width:200px;display:inline-block;vertical-align:top;" >
|
||||||
|
<table width="100%" style="border-spacing:0;font-family:sans-serif;color:#333333;" >
|
||||||
|
<tr>
|
||||||
|
<td class="inner contents" style="padding-top:10px;padding-bottom:10px;padding-right:10px;padding-left:10px;width:100%;font-size:14px;text-align:center;" >
|
||||||
|
<p class="h2" style="Margin:0;font-size:18px;font-weight:bold;Margin-bottom:12px;" >Fashion</p>
|
||||||
|
<p style="Margin:0;" >Class eleifend aptent taciti sociosqu ad litora torquent conubia</p>
|
||||||
|
<p style="Margin:0;" ><a href="#" style="color:#ee6a56;text-decoration:underline;" >Read requirements</a></p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<!--[if (gte mso 9)|(IE)]>
|
||||||
|
</td><td width="200" valign="top" style="padding-top:0;padding-bottom:0;padding-right:0;padding-left:0;" >
|
||||||
|
<![endif]-->
|
||||||
|
<div class="column" style="width:100%;max-width:200px;display:inline-block;vertical-align:top;" >
|
||||||
|
<table width="100%" style="border-spacing:0;font-family:sans-serif;color:#333333;" >
|
||||||
|
<tr>
|
||||||
|
<td class="inner contents" style="padding-top:10px;padding-bottom:10px;padding-right:10px;padding-left:10px;width:100%;font-size:14px;text-align:center;" >
|
||||||
|
<p class="h2" style="Margin:0;font-size:18px;font-weight:bold;Margin-bottom:12px;" >Photography</p>
|
||||||
|
<p style="Margin:0;" >Maecenas sed ante pellentesque, posuere leo id, eleifend dolor</p>
|
||||||
|
<p style="Margin:0;" ><a href="#" style="color:#ee6a56;text-decoration:underline;" >See examples</a></p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<!--[if (gte mso 9)|(IE)]>
|
||||||
|
</td><td width="200" valign="top" style="padding-top:0;padding-bottom:0;padding-right:0;padding-left:0;" >
|
||||||
|
<![endif]-->
|
||||||
|
<div class="column" style="width:100%;max-width:200px;display:inline-block;vertical-align:top;" >
|
||||||
|
<table width="100%" style="border-spacing:0;font-family:sans-serif;color:#333333;" >
|
||||||
|
<tr>
|
||||||
|
<td class="inner contents" style="padding-top:10px;padding-bottom:10px;padding-right:10px;padding-left:10px;width:100%;font-size:14px;text-align:center;" >
|
||||||
|
<p class="h2" style="Margin:0;font-size:18px;font-weight:bold;Margin-bottom:12px;" >Design</p>
|
||||||
|
<p style="Margin:0;" >Class aptent taciti sociosqu eleifend ad litora per conubia nostra</p>
|
||||||
|
<p style="Margin:0;" ><a href="#" style="color:#ee6a56;text-decoration:underline;" >See the winners</a></p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<!--[if (gte mso 9)|(IE)]>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td width="200" valign="top" style="padding-top:0;padding-bottom:0;padding-right:0;padding-left:0;" >
|
||||||
|
<![endif]-->
|
||||||
|
<div class="column" style="width:100%;max-width:200px;display:inline-block;vertical-align:top;" >
|
||||||
|
<table width="100%" style="border-spacing:0;font-family:sans-serif;color:#333333;" >
|
||||||
|
<tr>
|
||||||
|
<td class="inner contents" style="padding-top:10px;padding-bottom:10px;padding-right:10px;padding-left:10px;width:100%;font-size:14px;text-align:center;" >
|
||||||
|
<p class="h2" style="Margin:0;font-size:18px;font-weight:bold;Margin-bottom:12px;" >Cooking</p>
|
||||||
|
<p style="Margin:0;" >Class aptent taciti eleifend sociosqu ad litora torquent conubia</p>
|
||||||
|
<p style="Margin:0;" ><a href="#" style="color:#ee6a56;text-decoration:underline;" >Read recipes</a></p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<!--[if (gte mso 9)|(IE)]>
|
||||||
|
</td><td width="200" valign="top" style="padding-top:0;padding-bottom:0;padding-right:0;padding-left:0;" >
|
||||||
|
<![endif]-->
|
||||||
|
<div class="column" style="width:100%;max-width:200px;display:inline-block;vertical-align:top;" >
|
||||||
|
<table width="100%" style="border-spacing:0;font-family:sans-serif;color:#333333;" >
|
||||||
|
<tr>
|
||||||
|
<td class="inner contents" style="padding-top:10px;padding-bottom:10px;padding-right:10px;padding-left:10px;width:100%;font-size:14px;text-align:center;" >
|
||||||
|
<p class="h2" style="Margin:0;font-size:18px;font-weight:bold;Margin-bottom:12px;" >Woodworking</p>
|
||||||
|
<p style="Margin:0;" >Maecenas sed ante pellentesque, posuere leo id, eleifend dolor</p>
|
||||||
|
<p style="Margin:0;" ><a href="#" style="color:#ee6a56;text-decoration:underline;" >See examples</a></p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<!--[if (gte mso 9)|(IE)]>
|
||||||
|
</td><td width="200" valign="top" style="padding-top:0;padding-bottom:0;padding-right:0;padding-left:0;" >
|
||||||
|
<![endif]-->
|
||||||
|
<div class="column" style="width:100%;max-width:200px;display:inline-block;vertical-align:top;" >
|
||||||
|
<table width="100%" style="border-spacing:0;font-family:sans-serif;color:#333333;" >
|
||||||
|
<tr>
|
||||||
|
<td class="inner contents" style="padding-top:10px;padding-bottom:10px;padding-right:10px;padding-left:10px;width:100%;font-size:14px;text-align:center;" >
|
||||||
|
<p class="h2" style="Margin:0;font-size:18px;font-weight:bold;Margin-bottom:12px;" >Craft</p>
|
||||||
|
<p style="Margin:0;" >Class aptent taciti sociosqu ad eleifend litora per conubia nostra</p>
|
||||||
|
<p style="Margin:0;" ><a href="#" style="color:#ee6a56;text-decoration:underline;" >Vote now</a></p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<!--[if (gte mso 9)|(IE)]>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<![endif]-->
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="left-sidebar" style="padding-top:0;padding-bottom:0;padding-right:0;padding-left:0;text-align:center;font-size:0;" >
|
||||||
|
<!--[if (gte mso 9)|(IE)]>
|
||||||
|
<table width="100%" style="border-spacing:0;font-family:sans-serif;color:#333333;" >
|
||||||
|
<tr>
|
||||||
|
<td width="100" style="padding-top:0;padding-bottom:0;padding-right:0;padding-left:0;" >
|
||||||
|
<![endif]-->
|
||||||
|
<div class="column left" style="width:100%;display:inline-block;vertical-align:middle;max-width:100px;" >
|
||||||
|
<table width="100%" style="border-spacing:0;font-family:sans-serif;color:#333333;" >
|
||||||
|
<tr>
|
||||||
|
<td class="inner" style="padding-top:10px;padding-bottom:10px;padding-right:10px;padding-left:10px;" >
|
||||||
|
<img src="http://www.inbucket.org/email-assets/responsive/sidebar-01.jpg" width="80" alt="" style="border-width:0;" />
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<!--[if (gte mso 9)|(IE)]>
|
||||||
|
</td><td width="500" style="padding-top:0;padding-bottom:0;padding-right:0;padding-left:0;" >
|
||||||
|
<![endif]-->
|
||||||
|
<div class="column right" style="width:100%;display:inline-block;vertical-align:middle;max-width:500px;" >
|
||||||
|
<table width="100%" style="border-spacing:0;font-family:sans-serif;color:#333333;" >
|
||||||
|
<tr>
|
||||||
|
<td class="inner contents" style="padding-top:10px;padding-bottom:10px;padding-right:10px;padding-left:10px;width:100%;font-size:14px;text-align:center;" >
|
||||||
|
Praesent laoreet malesuada cursus. Maecenas scelerisque congue eros eu posuere. Praesent in felis ut velit pretium lobortis rhoncus ut erat. <a href="#" style="text-decoration:underline;color:#85ab70;" >Read on</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<!--[if (gte mso 9)|(IE)]>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<![endif]-->
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="right-sidebar" dir="rtl" style="padding-top:0;padding-bottom:0;padding-right:0;padding-left:0;text-align:center;font-size:0;" >
|
||||||
|
<!--[if (gte mso 9)|(IE)]>
|
||||||
|
<table width="100%" dir="rtl" style="border-spacing:0;font-family:sans-serif;color:#333333;" >
|
||||||
|
<tr>
|
||||||
|
<td width="100" style="padding-top:0;padding-bottom:0;padding-right:0;padding-left:0;" >
|
||||||
|
<![endif]-->
|
||||||
|
<div class="column left" dir="ltr" style="width:100%;display:inline-block;vertical-align:middle;max-width:100px;" >
|
||||||
|
<table width="100%" style="border-spacing:0;font-family:sans-serif;color:#333333;" >
|
||||||
|
<tr>
|
||||||
|
<td class="inner contents" style="padding-top:10px;padding-bottom:10px;padding-right:10px;padding-left:10px;width:100%;font-size:14px;text-align:center;" >
|
||||||
|
<img src="http://www.inbucket.org/email-assets/responsive/sidebar-02.jpg" width="80" alt="" style="border-width:0;" />
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<!--[if (gte mso 9)|(IE)]>
|
||||||
|
</td><td width="500" style="padding-top:0;padding-bottom:0;padding-right:0;padding-left:0;" >
|
||||||
|
<![endif]-->
|
||||||
|
<div class="column right" dir="ltr" style="width:100%;display:inline-block;vertical-align:middle;max-width:500px;" >
|
||||||
|
<table width="100%" style="border-spacing:0;font-family:sans-serif;color:#333333;" >
|
||||||
|
<tr>
|
||||||
|
<td class="inner contents" style="padding-top:10px;padding-bottom:10px;padding-right:10px;padding-left:10px;width:100%;font-size:14px;text-align:center;" >
|
||||||
|
Maecenas sed ante pellentesque, posuere leo id, eleifend dolor. Class aptent taciti sociosqu ad litora torquent per conubia nostra. <a href="#" style="text-decoration:underline;color:#70bbd9;" >Per inceptos</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<!--[if (gte mso 9)|(IE)]>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<![endif]-->
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<!--[if (gte mso 9)|(IE)]>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<![endif]-->
|
||||||
|
</div>
|
||||||
|
</center>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
Date: %DATE%
|
Date: %DATE%
|
||||||
To: %TO_ADDRESS%
|
To: %TO_ADDRESS%
|
||||||
From: %FROM_ADDRESS%
|
From: %FROM_ADDRESS%
|
||||||
Subject: tutsplus responsive
|
Subject: tutsplus responsive external CSS
|
||||||
MIME-Version: 1.0
|
MIME-Version: 1.0
|
||||||
Content-Type: text/html; charset="UTF-8"
|
Content-Type: text/html; charset="UTF-8"
|
||||||
|
|
||||||
|
|||||||
@@ -5,4 +5,6 @@ Subject: Swaks HTML
|
|||||||
MIME-Version: 1.0
|
MIME-Version: 1.0
|
||||||
Content-Type: text/html; charset="UTF-8"
|
Content-Type: text/html; charset="UTF-8"
|
||||||
|
|
||||||
This is a test of <b>HTML</b> at the <i>top</i> level.
|
<p style="font-family: 'Courier New', Courier, monospace;">
|
||||||
|
This is a test of <b>HTML</b> at the <i>top</i> level.
|
||||||
|
</p>
|
||||||
|
|||||||
@@ -53,5 +53,6 @@ swaks $* --data gmail.raw
|
|||||||
# Outlook test
|
# Outlook test
|
||||||
swaks $* --data outlook.raw
|
swaks $* --data outlook.raw
|
||||||
|
|
||||||
# Nonemime responsive HTML test
|
# Non-mime responsive HTML test
|
||||||
swaks $* --data nonmime-html-responsive.raw
|
swaks $* --data nonmime-html-responsive.raw
|
||||||
|
swaks $* --data nonmime-html-inlined.raw
|
||||||
|
|||||||
Reference in New Issue
Block a user