diff --git a/.github/workflows/close-stale-issues.yml b/.github/workflows/close-stale-issues.yml index 82088dd21..9e757d6d0 100644 --- a/.github/workflows/close-stale-issues.yml +++ b/.github/workflows/close-stale-issues.yml @@ -12,12 +12,12 @@ jobs: steps: - uses: actions/stale@v9.0.0 with: - days-before-issue-stale: 14 - days-before-issue-close: 7 + days-before-issue-stale: 7 + days-before-issue-close: 3 exempt-issue-labels: "enhancement,bug,javascript,docker" stale-issue-label: "stale" - stale-issue-message: "This issue is stale because it has been open for 14 days with no activity." - close-issue-message: "This issue was closed because it has been inactive for 7 days since being marked as stale." + stale-issue-message: "This issue has been marked as stale because it has been open for 7 days with no activity." + close-issue-message: "This issue was closed because there has been no activity since being marked as stale." days-before-pr-stale: -1 days-before-pr-close: -1 repo-token: ${{ secrets.GITHUB_TOKEN }} diff --git a/CHANGELOG.md b/CHANGELOG.md index fbf79fdda..5db1bbb24 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,26 @@ Notable changes to Mailpit will be documented in this file. +## [v1.17.0] + +### Chore +- Update caniemail database +- Update node dependencies +- Update Go dependencies +- Auto-rotate thumbnail images based on exif data +- Replace disintegration/imaging with kovidgoyal/imaging to fix CVE-2023-36308 +- Update API documentation regarding date/time searches & timezones +- Move Link check & HTML check features out of beta +- Remove deprecated --disable-html-check option + +### Feature +- Option to auto relay for matching recipient expression only ([#274](https://github.com/axllent/mailpit/issues/274)) +- Add UI settings screen + +### Fix +- Add delay to close database on fatal exit ([#280](https://github.com/axllent/mailpit/issues/280)) + + ## [v1.16.0] ### Chore diff --git a/cmd/root.go b/cmd/root.go index e38c5dc44..631e6ff25 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -34,14 +34,15 @@ Documentation: os.Exit(1) } if err := storage.InitDB(); err != nil { - logger.Log().Error(err.Error()) + logger.Log().Fatal(err.Error()) os.Exit(1) } go server.Listen() if err := smtpd.Listen(); err != nil { - logger.Log().Error(err.Error()) + storage.Close() + logger.Log().Fatal(err.Error()) os.Exit(1) } }, @@ -96,7 +97,6 @@ func init() { rootCmd.Flags().StringVar(&config.UITLSCert, "ui-tls-cert", config.UITLSCert, "TLS certificate for web UI (HTTPS) - requires ui-tls-key") rootCmd.Flags().StringVar(&config.UITLSKey, "ui-tls-key", config.UITLSKey, "TLS key for web UI (HTTPS) - requires ui-tls-cert") rootCmd.Flags().StringVar(&server.AccessControlAllowOrigin, "api-cors", server.AccessControlAllowOrigin, "Set API CORS Access-Control-Allow-Origin header") - rootCmd.Flags().BoolVar(&config.DisableHTMLCheck, "disable-html-check", config.DisableHTMLCheck, "Disable the HTML check functionality (web UI & API)") rootCmd.Flags().BoolVar(&config.BlockRemoteCSSAndFonts, "block-remote-css-and-fonts", config.BlockRemoteCSSAndFonts, "Block access to remote CSS & fonts") rootCmd.Flags().StringVar(&config.EnableSpamAssassin, "enable-spamassassin", config.EnableSpamAssassin, "Enable integration with SpamAssassin") rootCmd.Flags().BoolVar(&config.AllowUntrustedTLS, "allow-untrusted-tls", config.AllowUntrustedTLS, "Do not verify HTTPS certificates (link checker & screenshots)") @@ -116,8 +116,9 @@ func init() { rootCmd.Flags().BoolVar(&smtpd.DisableReverseDNS, "smtp-disable-rdns", smtpd.DisableReverseDNS, "Disable SMTP reverse DNS lookups") // SMTP relay - rootCmd.Flags().StringVar(&config.SMTPRelayConfigFile, "smtp-relay-config", config.SMTPRelayConfigFile, "SMTP configuration file to allow releasing messages") - rootCmd.Flags().BoolVar(&config.SMTPRelayAllIncoming, "smtp-relay-all", config.SMTPRelayAllIncoming, "Relay all incoming messages via external SMTP server (caution!)") + rootCmd.Flags().StringVar(&config.SMTPRelayConfigFile, "smtp-relay-config", config.SMTPRelayConfigFile, "SMTP relay configuration file to allow releasing messages") + rootCmd.Flags().BoolVar(&config.SMTPRelayAll, "smtp-relay-all", config.SMTPRelayAll, "Auto-relay all new messages via external SMTP server (caution!)") + rootCmd.Flags().StringVar(&config.SMTPRelayMatching, "smtp-relay-matching", config.SMTPRelayMatching, "Auto-relay new messages to only matching recipients (regular expression)") // POP3 server rootCmd.Flags().StringVar(&config.POP3Listen, "pop3", config.POP3Listen, "POP3 server bind interface and port") @@ -155,6 +156,10 @@ func init() { rootCmd.Flags().BoolVar(&config.SMTPRequireSTARTTLS, "smtp-tls-required", config.SMTPRequireSTARTTLS, "smtp-require-starttls") rootCmd.Flags().Lookup("smtp-tls-required").Hidden = true rootCmd.Flags().Lookup("smtp-tls-required").Deprecated = "use --smtp-require-starttls" + + // DEPRECATED FLAG 2024/04/13 - no longer used + rootCmd.Flags().BoolVar(&config.DisableHTMLCheck, "disable-html-check", config.DisableHTMLCheck, "Disable the HTML check functionality (web UI & API)") + rootCmd.Flags().Lookup("disable-html-check").Hidden = true } // Load settings from environment @@ -201,9 +206,6 @@ func initConfigFromEnv() { if len(os.Getenv("MP_API_CORS")) > 0 { server.AccessControlAllowOrigin = os.Getenv("MP_API_CORS") } - if getEnabledFromEnv("MP_DISABLE_HTML_CHECK") { - config.DisableHTMLCheck = true - } if getEnabledFromEnv("MP_BLOCK_REMOTE_CSS_AND_FONTS") { config.BlockRemoteCSSAndFonts = true } @@ -252,8 +254,9 @@ func initConfigFromEnv() { // SMTP relay config.SMTPRelayConfigFile = os.Getenv("MP_SMTP_RELAY_CONFIG") if getEnabledFromEnv("MP_SMTP_RELAY_ALL") { - config.SMTPRelayAllIncoming = true + config.SMTPRelayAll = true } + config.SMTPRelayMatching = os.Getenv("MP_SMTP_RELAY_MATCHING") config.SMTPRelayConfig = config.SMTPRelayConfigStruct{} config.SMTPRelayConfig.Host = os.Getenv("MP_SMTP_RELAY_HOST") if len(os.Getenv("MP_SMTP_RELAY_PORT")) > 0 { @@ -333,6 +336,10 @@ func initDeprecatedConfigFromEnv() { logger.Log().Warn("ENV MP_SMTP_TLS_REQUIRED has been deprecated, use MP_SMTP_REQUIRE_STARTTLS") config.SMTPRequireSTARTTLS = true } + if getEnabledFromEnv("MP_DISABLE_HTML_CHECK") { + logger.Log().Warn("ENV MP_DISABLE_HTML_CHECK has been deprecated and is no longer used") + config.DisableHTMLCheck = true + } } // Wrapper to get a boolean from an environment variable diff --git a/config/config.go b/config/config.go index c5522cbcb..906e190dd 100644 --- a/config/config.go +++ b/config/config.go @@ -83,9 +83,6 @@ var ( // IgnoreDuplicateIDs will skip messages with the same ID IgnoreDuplicateIDs bool - // DisableHTMLCheck used to disable the HTML check in bother the API and web UI - DisableHTMLCheck = false - // BlockRemoteCSSAndFonts used to disable remote CSS & fonts BlockRemoteCSSAndFonts = false @@ -117,9 +114,15 @@ var ( // ReleaseEnabled is whether message releases are enabled, requires a valid SMTPRelayConfigFile ReleaseEnabled = false - // SMTPRelayAllIncoming is whether to relay all incoming messages via pre-configured SMTP server. + // SMTPRelayAll is whether to relay all incoming messages via pre-configured SMTP server. // Use with extreme caution! - SMTPRelayAllIncoming = false + SMTPRelayAll = false + + // SMTPRelayMatching if set, will auto-release to recipients matching this regular expression + SMTPRelayMatching string + + // SMTPRelayMatchingRegexp is the compiled version of SMTPRelayMatching + SMTPRelayMatchingRegexp *regexp.Regexp // POP3Listen address - if set then Mailpit will start the POP3 server and listen on this address POP3Listen = "[::]:1110" @@ -153,6 +156,9 @@ var ( // RepoBinaryName on Github for updater RepoBinaryName = "mailpit" + + // DisableHTMLCheck DEPRECATED 2024/04/13 - kept here to display console warning only + DisableHTMLCheck = false ) // AutoTag struct for auto-tagging @@ -361,6 +367,11 @@ func VerifyConfig() error { return fmt.Errorf("webhook URL does not appear to be a valid URL (%s)", WebhookURL) } + // DEPRECATED 2024/04/13 + if DisableHTMLCheck { + logger.Log().Warn("--disable-html-check has been deprecated and is no longer used") + } + if EnableSpamAssassin != "" { spamassassin.SetService(EnableSpamAssassin) logger.Log().Infof("[spamassassin] enabled via %s", EnableSpamAssassin) @@ -400,7 +411,7 @@ func VerifyConfig() error { } SMTPAllowedRecipientsRegexp = restrictRegexp - logger.Log().Infof("[smtp] only allowing recipients matching the following regexp: %s", SMTPAllowedRecipients) + logger.Log().Infof("[smtp] only allowing recipients matching regexp: %s", SMTPAllowedRecipients) } if err := parseRelayConfig(SMTPRelayConfigFile); err != nil { @@ -412,13 +423,28 @@ func VerifyConfig() error { return err } - if !ReleaseEnabled && SMTPRelayAllIncoming { - return errors.New("[smtp] relay config must be set to relay all messages") + if !ReleaseEnabled && SMTPRelayAll || !ReleaseEnabled && SMTPRelayMatching != "" { + return errors.New("[relay] a relay configuration must be set to auto-relay any messages") } - if SMTPRelayAllIncoming { + if SMTPRelayMatching != "" { + if SMTPRelayAll { + logger.Log().Warnf("[relay] ignoring smtp-relay-matching when smtp-relay-all is enabled") + } else { + restrictRegexp, err := regexp.Compile(SMTPRelayMatching) + if err != nil { + return fmt.Errorf("[relay] failed to compile smtp-relay-matching regexp: %s", err.Error()) + } + + SMTPRelayMatchingRegexp = restrictRegexp + logger.Log().Infof("[relay] auto-relaying new messages to recipients matching \"%s\" via %s:%d", + SMTPRelayMatching, SMTPRelayConfig.Host, SMTPRelayConfig.Port) + } + } + + if SMTPRelayAll { // this deserves a warning - logger.Log().Warnf("[smtp] enabling automatic relay of all new messages via %s:%d", SMTPRelayConfig.Host, SMTPRelayConfig.Port) + logger.Log().Warnf("[relay] auto-relaying all new messages via %s:%d", SMTPRelayConfig.Host, SMTPRelayConfig.Port) } return nil @@ -451,7 +477,7 @@ func parseRelayConfig(c string) error { // DEPRECATED 2024/03/12 if SMTPRelayConfig.RecipientAllowlist != "" { - logger.Log().Warn("[smtp] relay 'recipient-allowlist' is deprecated, use 'allowed_recipients' instead") + logger.Log().Warn("[smtp] relay 'recipient-allowlist' is deprecated, use 'allowed-recipients' instead") if SMTPRelayConfig.AllowedRecipients == "" { SMTPRelayConfig.AllowedRecipients = SMTPRelayConfig.RecipientAllowlist } @@ -496,9 +522,8 @@ func validateRelayConfig() error { logger.Log().Infof("[smtp] enabling message relaying via %s:%d", SMTPRelayConfig.Host, SMTPRelayConfig.Port) - allowlistRegexp, err := regexp.Compile(SMTPRelayConfig.AllowedRecipients) - if SMTPRelayConfig.AllowedRecipients != "" { + allowlistRegexp, err := regexp.Compile(SMTPRelayConfig.AllowedRecipients) if err != nil { return fmt.Errorf("[smtp] failed to compile relay recipient allowlist regexp: %s", err.Error()) } diff --git a/go.mod b/go.mod index 279862c08..2e79060af 100644 --- a/go.mod +++ b/go.mod @@ -1,17 +1,19 @@ module github.com/axllent/mailpit -go 1.20 +go 1.21.0 + +toolchain go1.22.1 require ( github.com/PuerkitoBio/goquery v1.9.1 github.com/araddon/dateparse v0.0.0-20210429162001-6b43995a97de github.com/axllent/semver v0.0.1 - github.com/disintegration/imaging v1.6.2 - github.com/gomarkdown/markdown v0.0.0-20240328165702-4d01890c35c0 + github.com/gomarkdown/markdown v0.0.0-20240419095408-642f0ee99ae2 github.com/gorilla/mux v1.8.1 github.com/gorilla/websocket v1.5.1 github.com/jhillyerd/enmime v1.2.0 github.com/klauspost/compress v1.17.8 + github.com/kovidgoyal/imaging v1.6.3 github.com/leporo/sqlf v1.4.0 github.com/lithammer/shortuuid/v4 v4.0.0 github.com/mhale/smtpd v0.8.2 @@ -26,7 +28,7 @@ require ( golang.org/x/text v0.14.0 golang.org/x/time v0.5.0 gopkg.in/yaml.v3 v3.0.1 - modernc.org/sqlite v1.29.6 + modernc.org/sqlite v1.29.8 ) require ( diff --git a/go.sum b/go.sum index 10addbcfc..a2f3e0bdf 100644 --- a/go.sum +++ b/go.sum @@ -17,17 +17,17 @@ github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ3 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/disintegration/imaging v1.6.2 h1:w1LecBlG2Lnp8B3jk5zSuNqd7b4DXhcjwek1ei82L+c= -github.com/disintegration/imaging v1.6.2/go.mod h1:44/5580QXChDfwIclfc/PCwrr44amcmDAg8hxG0Ewe4= github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= github.com/eknkc/amber v0.0.0-20171010120322-cdade1c07385/go.mod h1:0vRUJqYpeSZifjYj7uP3BG/gKcuzL9xWVV/Y+cK33KM= github.com/go-test/deep v1.1.0 h1:WOcxcdHcvdgThNXjw0t76K42FXTU7HpNQWHpA2HHNlg= +github.com/go-test/deep v1.1.0/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE= github.com/gogs/chardet v0.0.0-20211120154057-b7413eaefb8f h1:3BSP1Tbs2djlpprl7wCLuiqMaUh5SJkkzI2gDs+FgLs= github.com/gogs/chardet v0.0.0-20211120154057-b7413eaefb8f/go.mod h1:Pcatq5tYkCW2Q6yrR2VRHlbHpZ/R4/7qyL1TCF7vl14= -github.com/gomarkdown/markdown v0.0.0-20240328165702-4d01890c35c0 h1:4gjrh/PN2MuWCCElk8/I4OCKRKWCCo2zEct3VKCbibU= -github.com/gomarkdown/markdown v0.0.0-20240328165702-4d01890c35c0/go.mod h1:JDGcbDT52eL4fju3sZ4TeHGsQwhG9nbDV21aMyhwPoA= -github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26 h1:Xim43kblpZXfIBQsbuBVKCudVG457BR2GZFIz3uw3hQ= +github.com/gomarkdown/markdown v0.0.0-20240419095408-642f0ee99ae2 h1:yEt5djSYb4iNtmV9iJGVday+i4e9u6Mrn5iP64HH5QM= +github.com/gomarkdown/markdown v0.0.0-20240419095408-642f0ee99ae2/go.mod h1:JDGcbDT52eL4fju3sZ4TeHGsQwhG9nbDV21aMyhwPoA= +github.com/google/pprof v0.0.0-20240409012703-83162a5b38cd h1:gbpYu9NMq8jhDVbvlGkMFWCjLFlqqEZjEmObmhUy6Vo= +github.com/google/pprof v0.0.0-20240409012703-83162a5b38cd/go.mod h1:kf6iHlnVGwgKolg33glAes7Yg/8iWP8ukqeldJSO7jw= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= @@ -48,6 +48,8 @@ github.com/jhillyerd/enmime v1.2.0 h1:dIu1IPEymQgoT2dzuB//ttA/xcV40NMPpQtmd4wslH github.com/jhillyerd/enmime v1.2.0/go.mod h1:FRFuUPCLh8PByQv+8xRcLO9QHqaqTqreYhopv5eyk4I= github.com/klauspost/compress v1.17.8 h1:YcnTYrq7MikUT7k0Yb5eceMmALQPYBW/Xltxn0NAMnU= github.com/klauspost/compress v1.17.8/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= +github.com/kovidgoyal/imaging v1.6.3 h1:iNPpv7ygiaB/NOztc6APMT7yr9UwBS+rOZwIbAdtyY8= +github.com/kovidgoyal/imaging v1.6.3/go.mod h1:sHvcLOOVhJuto2IoNdPLEqnAUoL5ZfHEF0PpNH+882g= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= @@ -67,6 +69,7 @@ github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZ github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mattn/go-sqlite3 v1.14.16/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg= github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU= +github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= github.com/mhale/smtpd v0.8.2 h1:rHKOMHeFoDvcq8Na9ErCbNcjlWTSyGtznOmJpWsOzuc= github.com/mhale/smtpd v0.8.2/go.mod h1:MQl+y2hwIEQCXtNhe5+55n0GZOjSmeqORDIXbqUL3x4= github.com/ncruces/go-strftime v0.1.9 h1:bY0MQC28UADQmHmaF5dgpLmImcShSi2kHU9XLdhx/f4= @@ -110,6 +113,7 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/tg123/go-htpasswd v1.2.2 h1:tmNccDsQ+wYsoRfiONzIhDm5OkVHQzN3w4FOBAlN6BY= github.com/tg123/go-htpasswd v1.2.2/go.mod h1:FcIrK0J+6zptgVwK1JDlqyajW/1B4PtuJ/FLWl7nx8A= github.com/unrolled/render v1.0.3/go.mod h1:gN9T0NhL4Bfbwu8ann7Ry/TGHYfosul+J0obPf6NBdM= @@ -126,12 +130,12 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30= golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M= -golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/image v0.15.0 h1:kOELfmgrmJlw4Cdb7g/QGuB3CvDrXbqEIww/pNtNBm8= golang.org/x/image v0.15.0/go.mod h1:HUYqC05R2ZcZ3ejNQsIHQDQiwWM4JBqmm6MKANTp4LE= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.16.0 h1:QX4fJ0Rr5cPQCF7O9lh9Se4pmwfwskqZfq5moyldzic= +golang.org/x/mod v0.16.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -177,6 +181,7 @@ golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.19.0 h1:tfGCXNR1OsFG+sVdLAitlpjAvD/I6dHDKnYrpEZUHkw= +golang.org/x/tools v0.19.0/go.mod h1:qoJWxmGSIBmAeriMx19ogtrEPrGtDbPK634QFIcLAhc= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -187,9 +192,13 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= modernc.org/cc/v4 v4.20.0 h1:45Or8mQfbUqJOG9WaxvlFYOAQO0lQ5RvqBcFCXngjxk= +modernc.org/cc/v4 v4.20.0/go.mod h1:HM7VJTZbUCR3rV8EYBi9wxnJ0ZBRiGE5OeGXNA0IsLQ= modernc.org/ccgo/v4 v4.16.0 h1:ofwORa6vx2FMm0916/CkZjpFPSR70VwTjUCe2Eg5BnA= +modernc.org/ccgo/v4 v4.16.0/go.mod h1:dkNyWIjFrVIZ68DTo36vHK+6/ShBn4ysU61So6PIqCI= modernc.org/fileutil v1.3.0 h1:gQ5SIzK3H9kdfai/5x41oQiKValumqNTDXMvKo62HvE= +modernc.org/fileutil v1.3.0/go.mod h1:XatxS8fZi3pS8/hKG2GH/ArUogfxjpEKs3Ku3aK4JyQ= modernc.org/gc/v2 v2.4.1 h1:9cNzOqPyMJBvrUipmynX0ZohMhcxPtMccYgGOJdOiBw= +modernc.org/gc/v2 v2.4.1/go.mod h1:wzN5dK1AzVGoH6XOzc3YZ+ey/jPgYHLuVckd62P0GYU= modernc.org/gc/v3 v3.0.0-20240304020402-f0dba7c97c2b h1:BnN1t+pb1cy61zbvSUV7SeI0PwosMhlAEi/vBY4qxp8= modernc.org/gc/v3 v3.0.0-20240304020402-f0dba7c97c2b/go.mod h1:Qz0X07sNOR1jWYCrJMEnbW/X55x206Q7Vt4mz6/wHp4= modernc.org/libc v1.49.3 h1:j2MRCRdwJI2ls/sGbeSk0t2bypOG/uvPZUsGQFDulqg= @@ -199,9 +208,11 @@ modernc.org/mathutil v1.6.0/go.mod h1:Ui5Q9q1TR2gFm0AQRqQUaBWFLAhQpCwNcuhBOSedWP modernc.org/memory v1.8.0 h1:IqGTL6eFMaDZZhEWwcREgeMXYwmW83LYW8cROZYkg+E= modernc.org/memory v1.8.0/go.mod h1:XPZ936zp5OMKGWPqbD3JShgd/ZoQ7899TUuQqxY+peU= modernc.org/opt v0.1.3 h1:3XOZf2yznlhC+ibLltsDGzABUGVx8J6pnFMS3E4dcq4= +modernc.org/opt v0.1.3/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0= modernc.org/sortutil v1.2.0 h1:jQiD3PfS2REGJNzNCMMaLSp/wdMNieTbKX920Cqdgqc= -modernc.org/sqlite v1.29.6 h1:0lOXGrycJPptfHDuohfYgNqoe4hu+gYuN/pKgY5XjS4= -modernc.org/sqlite v1.29.6/go.mod h1:S02dvcmm7TnTRvGhv8IGYyLnIt7AS2KPaB1F/71p75U= +modernc.org/sortutil v1.2.0/go.mod h1:TKU2s7kJMf1AE84OoiGppNHJwvB753OYfNl2WRb++Ss= +modernc.org/sqlite v1.29.8 h1:nGKglNx9K5v0As+zF0/Gcl1kMkmaU1XynYyq92PbsC8= +modernc.org/sqlite v1.29.8/go.mod h1:lQPm27iqa4UNZpmr4Aor0MH0HkCLbt1huYDfWylLZFk= modernc.org/strutil v1.2.0 h1:agBi9dp1I+eOnxXeiZawM8F4LawKv4NzGWSaLfyeNZA= modernc.org/strutil v1.2.0/go.mod h1:/mdcBmfOibveCTBxUl5B5l6W+TTH1FXPLHZE6bTosX0= modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y= diff --git a/internal/htmlcheck/caniemail-data.json b/internal/htmlcheck/caniemail-data.json index 327e51230..448c1833c 100644 --- a/internal/htmlcheck/caniemail-data.json +++ b/internal/htmlcheck/caniemail-data.json @@ -1,6 +1,6 @@ { "api_version":"1.0.4", - "last_update_date":"2024-04-03 12:33:14 +0000", + "last_update_date":"2024-04-19 09:12:53 +0000", "nicenames":{"family":{"gmail":"Gmail","outlook":"Outlook","yahoo":"Yahoo! Mail","apple-mail":"Apple Mail","aol":"AOL","thunderbird":"Mozilla Thunderbird","microsoft":"Microsoft","samsung-email":"Samsung Email","sfr":"SFR","orange":"Orange","protonmail":"ProtonMail","hey":"HEY","mail-ru":"Mail.ru","fastmail":"Fastmail","laposte":"LaPoste.net","t-online-de":"T-online.de","free-fr":"Free.fr","gmx":"GMX","web-de":"WEB.DE","ionos-1and1":"1&1","rainloop":"RainLoop","wp-pl":"WP.pl"},"platform":{"desktop-app":"Desktop","desktop-webmail":"Desktop Webmail","mobile-webmail":"Mobile Webmail","webmail":"Webmail","ios":"iOS","android":"Android","windows":"Windows","macos":"macOS","windows-mail":"Windows Mail","outlook-com":"Outlook.com"},"support":{"supported":"Supported","mitigated":"Partially supported","unsupported":"Not supported","unknown":"Support unknown","mixed":"Mixed support"},"category":{"html":"HTML","css":"CSS","image":"Image formats","others":"Others"}}, "data":[ { @@ -62,7 +62,7 @@ "last_test_date":"2023-12-19", "test_url":"https://www.caniemail.com/tests/css-align-items.html", "test_results_url":"https://app.emailonacid.com/app/acidtest/FvYneb1dhiR4we6rAOf4AC02oFa6ksA0sTWxbEjgmt6Mg/list", - "stats":{"apple-mail":{"macos":{"11":"y","12":"y","13":"y"},"ios":{"11":"y","12":"y","13":"y","14":"y"}},"gmail":{"desktop-webmail":{"2020-12":"n"},"ios":{"2020-12":"n"},"android":{"2020-12":"n"},"mobile-webmail":{"2020-12":"n"}},"orange":{"desktop-webmail":{"2021-02":"y","2021-03":"n"},"ios":{"2021-03":"y"},"android":{"2021-03":"y"}},"outlook":{"windows":{"2007":"n","2010":"n","2013":"n","2016":"n","2019":"n"},"windows-mail":{"2020-12":"n"},"macos":{"2020-12":"y","16.80":"y"},"outlook-com":{"2020-12":"y"},"ios":{"2020-12":"y"},"android":{"4.2048.4":"y"}},"yahoo":{"desktop-webmail":{"2020-12":"n"},"ios":{"2021-03":"n"},"android":{"6.16.2.1519779":"n"}},"aol":{"desktop-webmail":{"2020-12":"n"},"ios":{"2021-03":"n"},"android":{"2021-03":"n"}},"samsung-email":{"android":{"6.1.31.2":"y"}},"sfr":{"desktop-webmail":{"2021-03":"y"},"ios":{"2021-03":"y"},"android":{"2021-03":"y"}},"thunderbird":{"macos":{"2020-12":"y"}},"protonmail":{"desktop-webmail":{"2021-03":"y"},"ios":{"2021-03":"y"},"android":{"2021-03":"y"}},"hey":{"desktop-webmail":{"2021-03":"y"}},"mail-ru":{"desktop-webmail":{"2020-12":"y"}},"fastmail":{"desktop-webmail":{"2021-07":"y"}},"laposte":{"desktop-webmail":{"2021-08":"y #1"}},"gmx":{"desktop-webmail":{"2022-06":"n"},"ios":{"2022-06":"y"},"android":{"2022-06":"y"}},"web-de":{"desktop-webmail":{"2022-06":"n"},"ios":{"2022-06":"y"},"android":{"2022-06":"y"}},"ionos-1and1":{"desktop-webmail":{"2022-06":"y"},"android":{"2022-06":"y"}}}, + "stats":{"apple-mail":{"macos":{"11":"y","12":"y","13":"y"},"ios":{"11":"y","12":"y","13":"y","14":"y"}},"gmail":{"desktop-webmail":{"2020-12":"n"},"ios":{"2020-12":"n"},"android":{"2020-12":"n"},"mobile-webmail":{"2020-12":"n"}},"orange":{"desktop-webmail":{"2021-02":"y","2021-03":"n"},"ios":{"2021-03":"y","2024-04":"n"},"android":{"2021-03":"y","2024-04":"n"}},"outlook":{"windows":{"2007":"n","2010":"n","2013":"n","2016":"n","2019":"n"},"windows-mail":{"2020-12":"n"},"macos":{"2020-12":"y","16.80":"y"},"outlook-com":{"2020-12":"y"},"ios":{"2020-12":"y"},"android":{"4.2048.4":"y"}},"yahoo":{"desktop-webmail":{"2020-12":"n"},"ios":{"2021-03":"n"},"android":{"6.16.2.1519779":"n"}},"aol":{"desktop-webmail":{"2020-12":"n"},"ios":{"2021-03":"n"},"android":{"2021-03":"n"}},"samsung-email":{"android":{"6.1.31.2":"y"}},"sfr":{"desktop-webmail":{"2021-03":"y"},"ios":{"2021-03":"y"},"android":{"2021-03":"y"}},"thunderbird":{"macos":{"2020-12":"y"}},"protonmail":{"desktop-webmail":{"2021-03":"y"},"ios":{"2021-03":"y"},"android":{"2021-03":"y"}},"hey":{"desktop-webmail":{"2021-03":"y"}},"mail-ru":{"desktop-webmail":{"2020-12":"y"}},"fastmail":{"desktop-webmail":{"2021-07":"y"}},"laposte":{"desktop-webmail":{"2021-08":"y #1"}},"gmx":{"desktop-webmail":{"2022-06":"n"},"ios":{"2022-06":"y"},"android":{"2022-06":"y"}},"web-de":{"desktop-webmail":{"2022-06":"n"},"ios":{"2022-06":"y"},"android":{"2022-06":"y"}},"ionos-1and1":{"desktop-webmail":{"2022-06":"y"},"android":{"2022-06":"y"}}}, "notes":null, "notes_by_num":{"1":"Supported. But a default style of `margin:auto` is applied on every element and can prevent the expected result."} }, @@ -110,9 +110,9 @@ "last_test_date":"2023-12-19", "test_url":"https://www.caniemail.com/tests/css-font-face.html", "test_results_url":"https://app.emailonacid.com/app/acidtest/veY9MhuhgFeF1ly5crrhTXawfLJSwxgpYi27OElI7iSoc/list", - "stats":{"apple-mail":{"macos":{"12.2":"y"},"ios":{"10.3":"y","12.3.1":"y"}},"gmail":{"desktop-webmail":{"2019-07":"n #6"},"ios":{"2019-07":"n"},"android":{"2019-07":"n"},"mobile-webmail":{"2020-02":"n"}},"orange":{"desktop-webmail":{"2019-05":"a #2","2021-03":"n #7"},"ios":{"2019-07":"y","2024-03":"n"},"android":{"2019-07":"a #1"}},"outlook":{"windows":{"2003":"a #3","2007":"a #4 #5","2010":"a #4 #5","2013":"a #4 #5","2016":"a #4 #5","2019":"a #4"},"windows-mail":{"2020-01":"n"},"macos":{"2011":"y","2016":"y","16.80":"n"},"outlook-com":{"2019-07":"n","2023-12":"n"},"ios":{"2.51.1":"y","3.29.0":"n"},"android":{"2019-07":"n"}},"samsung-email":{"android":{"6.0":"y #8","2021-11":"y #8"}},"sfr":{"desktop-webmail":{"2019-07":"a #2"},"ios":{"2019-07":"n"},"android":{"2019-07":"n"}},"thunderbird":{"macos":{"60.7":"y","78.5":"y"}},"aol":{"desktop-webmail":{"2020-01":"n"},"ios":{"2020-01":"n"},"android":{"2020-01":"n"}},"yahoo":{"desktop-webmail":{"2019-07":"n"},"ios":{"2019-07":"n"},"android":{"2019-07":"n"}},"protonmail":{"desktop-webmail":{"2020-03":"n"},"ios":{"2020-03":"n"},"android":{"2020-03":"y"}},"hey":{"desktop-webmail":{"2020-06":"y"}},"mail-ru":{"desktop-webmail":{"2020-10":"n"}},"fastmail":{"desktop-webmail":{"2021-07":"n"}},"laposte":{"desktop-webmail":{"2021-08":"a #2"}},"gmx":{"desktop-webmail":{"2022-06":"n"},"ios":{"2022-06":"y"},"android":{"2022-06":"n"}},"web-de":{"desktop-webmail":{"2022-06":"n"},"ios":{"2022-06":"y"},"android":{"2022-06":"n"}},"ionos-1and1":{"desktop-webmail":{"2022-06":"y"},"android":{"2022-06":"n"}}}, + "stats":{"apple-mail":{"macos":{"12.2":"y"},"ios":{"10.3":"y","12.3.1":"y"}},"gmail":{"desktop-webmail":{"2019-07":"n #6"},"ios":{"2019-07":"n"},"android":{"2019-07":"n"},"mobile-webmail":{"2020-02":"n"}},"orange":{"desktop-webmail":{"2019-05":"a #2","2021-03":"n #7","2024-03":"n"},"ios":{"2019-07":"y","2024-03":"n"},"android":{"2019-07":"a #1","2024-04":"n"}},"outlook":{"windows":{"2003":"a #3","2007":"a #4 #5","2010":"a #4 #5","2013":"a #4 #5","2016":"a #4 #5","2019":"a #4"},"windows-mail":{"2020-01":"n"},"macos":{"2011":"y","2016":"y","16.80":"n"},"outlook-com":{"2019-07":"n","2023-12":"n"},"ios":{"2.51.1":"y","3.29.0":"n"},"android":{"2019-07":"n"}},"samsung-email":{"android":{"6.0":"y #8","2021-11":"y #8"}},"sfr":{"desktop-webmail":{"2019-07":"a #2"},"ios":{"2019-07":"n"},"android":{"2019-07":"n"}},"thunderbird":{"macos":{"60.7":"y","78.5":"y"}},"aol":{"desktop-webmail":{"2020-01":"n"},"ios":{"2020-01":"n"},"android":{"2020-01":"n"}},"yahoo":{"desktop-webmail":{"2019-07":"n"},"ios":{"2019-07":"n"},"android":{"2019-07":"n"}},"protonmail":{"desktop-webmail":{"2020-03":"n"},"ios":{"2020-03":"n"},"android":{"2020-03":"y"}},"hey":{"desktop-webmail":{"2020-06":"y"}},"mail-ru":{"desktop-webmail":{"2020-10":"n"}},"fastmail":{"desktop-webmail":{"2021-07":"n"}},"laposte":{"desktop-webmail":{"2021-08":"a #2"}},"gmx":{"desktop-webmail":{"2022-06":"n"},"ios":{"2022-06":"y"},"android":{"2022-06":"n"}},"web-de":{"desktop-webmail":{"2022-06":"n"},"ios":{"2022-06":"y"},"android":{"2022-06":"n"}},"ionos-1and1":{"desktop-webmail":{"2022-06":"y"},"android":{"2022-06":"n"}}}, "notes":null, - "notes_by_num":{"1":"Partial. Only supported through a `` tag.","2":"Partial. Only supported directly through a `