sanitize_email 2.0.9 → 2.0.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/README.md CHANGED
@@ -1,227 +1,30 @@
1
- # sanitize_email
2
-
3
- [![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](https://opensource.org/licenses/MIT)
4
- [![Version](https://img.shields.io/gem/v/sanitize_email.svg)](https://rubygems.org/gems/sanitize_email)
5
- [![Downloads Today](https://img.shields.io/gem/rd/sanitize_email.svg)](https://github.com/pboling/sanitize_email)
6
- [![Depfu][🔑depfui]][🔑depfu]
7
- [![CodeCov][🖇codecov-img♻️]][🖇codecov]
8
- [![Test Coverage][🔑cc-covi]][🔑cc-cov]
9
- [![Maintainability][🔑cc-mnti]][🔑cc-mnt]
10
- [![CI Supported Build][🚎s-wfi]][🚎s-wf]
11
- [![CI Unsupported Build][🚎us-wfi]][🚎us-wf]
12
- [![CI Style Build][🚎st-wfi]][🚎st-wf]
13
- [![CI Coverage Build][🚎cov-wfi]][🚎cov-wf]
14
- [![CI Heads Build][🚎hd-wfi]][🚎hd-wf]
15
- [![CI Ancient Build][🚎an-wfi]][🚎an-wf]
16
-
17
- [🖇codecov-img♻️]: https://codecov.io/gh/pboling/sanitize_email/graph/badge.svg?token=selEoMrZzA
18
- [🖇codecov]: https://codecov.io/gh/pboling/sanitize_email
19
- [🚎s-wf]: https://github.com/pboling/sanitize_email/actions/workflows/supported.yml
20
- [🚎s-wfi]: https://github.com/pboling/sanitize_email/actions/workflows/supported.yml/badge.svg
21
- [🚎us-wf]: https://github.com/pboling/sanitize_email/actions/workflows/unsupported.yml
22
- [🚎us-wfi]: https://github.com/pboling/sanitize_email/actions/workflows/unsupported.yml/badge.svg
23
- [🚎st-wf]: https://github.com/pboling/sanitize_email/actions/workflows/style.yml
24
- [🚎st-wfi]: https://github.com/pboling/sanitize_email/actions/workflows/style.yml/badge.svg
25
- [🚎cov-wf]: https://github.com/pboling/sanitize_email/actions/workflows/coverage.yml
26
- [🚎cov-wfi]: https://github.com/pboling/sanitize_email/actions/workflows/coverage.yml/badge.svg
27
- [🚎hd-wf]: https://github.com/pboling/sanitize_email/actions/workflows/heads.yml
28
- [🚎hd-wfi]: https://github.com/pboling/sanitize_email/actions/workflows/heads.yml/badge.svg
29
- [🚎an-wf]: https://github.com/pboling/sanitize_email/actions/workflows/ancient.yml
30
- [🚎an-wfi]: https://github.com/pboling/sanitize_email/actions/workflows/ancient.yml/badge.svg
31
-
32
- -----
33
-
34
- [![Liberapay Patrons][⛳liberapay-img]][⛳liberapay]
35
- [![Sponsor Me on Github][🖇sponsor-img]][🖇sponsor]
36
- [![Polar Shield][🖇polar-img]][🖇polar]
37
- [![Donate to my FLOSS or refugee efforts at ko-fi.com][🖇kofi-img]][🖇kofi]
38
- [![Donate to my FLOSS or refugee efforts using Patreon][🖇patreon-img]][🖇patreon]
39
-
40
- [⛳liberapay-img]: https://img.shields.io/liberapay/patrons/pboling.svg?logo=liberapay
41
- [⛳liberapay]: https://liberapay.com/pboling/donate
42
- [🖇sponsor-img]: https://img.shields.io/badge/Sponsor_Me!-pboling.svg?style=social&logo=github
43
- [🖇sponsor]: https://github.com/sponsors/pboling
44
- [🖇polar-img]: https://polar.sh/embed/seeks-funding-shield.svg?org=pboling
45
- [🖇polar]: https://polar.sh/pboling
46
- [🖇kofi-img]: https://img.shields.io/badge/buy%20me%20coffee-donate-yellow.svg
47
- [🖇kofi]: https://ko-fi.com/O5O86SNP4
48
- [🖇patreon-img]: https://img.shields.io/badge/patreon-donate-yellow.svg
49
- [🖇patreon]: https://patreon.com/galtzo
50
-
51
- [comment]: <> ( 🔑 KEYED LINKS )
52
-
53
- [🔑cc-mnt]: https://codeclimate.com/github/pboling/sanitize_email/maintainability
54
- [🔑cc-mnti]: https://api.codeclimate.com/v1/badges/65af4948d859903a0372/maintainability
55
- [🔑cc-cov]: https://codeclimate.com/github/pboling/sanitize_email/test_coverage
56
- [🔑cc-covi]: https://api.codeclimate.com/v1/badges/65af4948d859903a0372/test_coverage
57
- [🔑depfu]: https://depfu.com/github/pboling/sanitize_email
58
- [🔑depfui]: https://badges.depfu.com/badges/bba430e8f19a2ba3273fb20d5e8c82d6/count.svg
59
-
60
- This gem allows you to override your mail delivery settings, globally or in a local context.
61
- It is like a Ruby encrusted condom for your email server,
62
- just in case it decides to have intercourse with other servers via sundry mail protocols.
1
+ [![Galtzo FLOSS Logo by Aboling0, CC BY-SA 4.0][🖼️galtzo-floss-i]][🖼️galtzo-floss] [![ruby-lang Logo, Yukihiro Matsumoto, Ruby Visual Identity Team, CC BY-SA 2.5][🖼️ruby-lang-i]][🖼️ruby-lang]
63
2
 
64
- Seriously though, this gem solves similar problems as the excellent [mailcatcher](https://mailcatcher.me/) gem,
65
- and `mailcatcher` solves those problems far more easily.
3
+ [🖼️galtzo-floss-i]: https://logos.galtzo.com/assets/images/galtzo-floss/avatar-192px.svg
4
+ [🖼️galtzo-floss]: https://discord.gg/3qme4XHNKN
5
+ [🖼️ruby-lang-i]: https://logos.galtzo.com/assets/images/ruby-lang/avatar-192px.svg
6
+ [🖼️ruby-lang]: https://www.ruby-lang.org/
66
7
 
67
- In addition, this gem solves problems that `mailcatcher` does not solve. I recommend using both!
8
+ # 📧 SanitizeEmail
68
9
 
69
- To make an analogy, `mailcatcher` is akin to `webmock`, entirely preventing interaction with your real live mail server,
70
- while this gem allows you to effectively use your real live (production!) mail server, while
71
- intercepting and modifying recipients on the way out, so that testing emails go to safe locations.
10
+ [![Version][👽versioni]][👽version] [![GitHub tag (latest SemVer)][⛳️tag-img]][⛳️tag] [![License: MIT][📄license-img]][📄license] [![Downloads Rank][👽dl-ranki]][👽dl-rank] [![CodeCov Test Coverage][🏀codecovi]][🏀codecov] [![Coveralls Test Coverage][🏀coveralls-img]][🏀coveralls] [![QLTY Test Coverage][🏀qlty-covi]][🏀qlty-cov] [![QLTY Maintainability][🏀qlty-mnti]][🏀qlty-mnt] [![CI Heads][🚎3-hd-wfi]][🚎3-hd-wf] [![CI Runtime Dependencies @ HEAD][🚎12-crh-wfi]][🚎12-crh-wf] [![CI Current][🚎11-c-wfi]][🚎11-c-wf] [![CI Truffle Ruby][🚎9-t-wfi]][🚎9-t-wf] [![CI JRuby][🚎10-j-wfi]][🚎10-j-wf] [![Deps Locked][🚎13-🔒️-wfi]][🚎13-🔒️-wf] [![Deps Unlocked][🚎14-🔓️-wfi]][🚎14-🔓️-wf] [![CI Test Coverage][🚎2-cov-wfi]][🚎2-cov-wf] [![CI Style][🚎5-st-wfi]][🚎5-st-wf] [![Apache SkyWalking Eyes License Compatibility Check][🚎15-🪪-wfi]][🚎15-🪪-wf]
72
11
 
73
- It is a bit like using the "test" Visa credit card number `4701322211111234` with a real payment gateway.
12
+ `if ci_badges.map(&:color).detect { it != "green"}` ☝️ [let me know][🖼️galtzo-floss], as I may have missed the [discord notification][🖼️galtzo-floss].
74
13
 
75
- ## Encryption
14
+ ---
76
15
 
77
- Making special note of this use case because it is important for companies working on HIPAA-compliant products.
78
- When you are sending emails through an encrypted email provider, e.g. [Paubox](https://www.paubox.com/),
79
- testing your email in the aforementioned `mailcatcher` may not be enough.
16
+ `if ci_badges.map(&:color).all? { it == "green"}` 👇️ send money so I can do more of this. FLOSS maintenance is now my full-time job.
80
17
 
81
- If you want to test all the way through Paubox's system, but have the email go to a safe testing account address,
82
- then this is the gem for you.
18
+ [![Sponsor Me on Github][🖇sponsor-img]][🖇sponsor] [![Liberapay Goal Progress][⛳liberapay-img]][⛳liberapay] [![Donate on PayPal][🖇paypal-img]][🖇paypal] [![Buy me a coffee][🖇buyme-small-img]][🖇buyme] [![Donate on Polar][🖇polar-img]][🖇polar] [![Donate at ko-fi.com][🖇kofi-img]][🖇kofi]
83
19
 
84
- ## Compatibility
20
+ <details>
21
+ <summary>👣 How will this project approach the September 2025 hostile takeover of RubyGems? 🚑️</summary>
85
22
 
86
- - ⚙️ Compatible with all versions of Ruby >= 2.3, plus JRuby and Truffleruby.
87
- - ⚙️ Compatible with all Ruby web Frameworks (Hanami, Roda, Sinatra, Rails).
88
- - ⚙️ Compatible with all versions of Rails from 3.0 - 7.1+.
89
- - ⚙️ Compatible with scripted usage of Mail gem outside a web framework.
90
- - ⚙️ Compatible with [`sendgrid-actionmailer`](https://github.com/eddiezane/sendgrid-actionmailer)'s support for personalizations, and will override email addresses there according to the configuration.
91
- - ⚙️ If this gem is not compatible with your use case, and you'd like it to be, I'd like to hear about it!
23
+ I've summarized my thoughts in [this blog post](https://dev.to/galtzo/hostile-takeover-of-rubygems-my-thoughts-5hlo).
92
24
 
93
- It was a slog getting (very nearly) the entire compatibility matrix working with Github Actions, [appraisal](https://github.com/thoughtbot/appraisal), and [combustion](https://github.com/pat/combustion), and I'm very interested in hearing about ways to improve it!
94
-
95
- ## 🛞 DVCS
96
-
97
- This project does not trust any one version control system,
98
- so it abides the principles of ["Distributed Version Control Systems"][💎d-in-dvcs]
99
-
100
- Find this project on:
101
-
102
- | Any | Of | These | DVCS |
103
- |----------------|------------------|----------------|----------------|
104
- | [🐙hub][🐙hub] | [🧊berg][🧊berg] | [🛖hut][🛖hut] | [🧪lab][🧪lab] |
105
-
106
- [comment]: <> ( DVCS LINKS )
107
-
108
- [💎d-in-dvcs]: https://railsbling.com/posts/dvcs/put_the_d_in_dvcs/
25
+ </details>
109
26
 
110
- [🧊berg]: https://codeberg.org/pboling/sanitize_email
111
- [🐙hub]: https://gitlab.com/pboling/sanitize_email
112
- [🛖hut]: https://sr.ht/~galtzo/pboling/sanitize_email
113
- [🧪lab]: https://gitlab.com/pboling/sanitize_email
114
-
115
- <!--
116
- Numbering rows and badges in each row as a visual "database" lookup,
117
- as the table is extremely dense, and it can be very difficult to find anything
118
- Putting one on each row here, to document the emoji that should be used, and for ease of copy/paste.
119
-
120
- row #s:
121
- 1️⃣
122
- 2️⃣
123
- 3️⃣
124
- 4️⃣
125
- 5️⃣
126
- 6️⃣
127
- 7️⃣
128
-
129
- badge #s:
130
- ⛳️
131
- 🖇
132
- 🏘
133
- 🚎
134
- 🖐
135
- 🧮
136
- 📗
137
-
138
- appended indicators:
139
- ♻️ / 🔑 - Tagged URLs need to be updated from SAAS integration. Find / Replace is insufficient.
140
- -->
141
-
142
- | | Project | bundle add sanitize_email |
143
- |:----|--------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
144
- | 1️⃣ | name, license, docs, standards | [![RubyGems.org][⛳️name-img]][⛳️gem] [![License: MIT][🖇src-license-img]][🖇src-license] [![RubyDoc.info][🚎yard-img]][🚎yard] [![YARD Documentation](http://inch-ci.org/github/pboling/sanitize_email.svg)][🚎yard] [![SemVer 2.0.0][🧮semver-img]][🧮semver] [![Keep-A-Changelog 1.0.0][📗keep-changelog-img]][📗keep-changelog] |
145
- | 2️⃣ | version & activity | [![Gem Version][⛳️version-img]][⛳️gem] [![Total Downloads][🖇DL-total-img]][⛳️gem] [![Download Rank][🏘DL-rank-img]][⛳️gem] [![Source Code][🚎src-main-img]][🚎src-main] [![Open PRs][🖐prs-o-img]][🖐prs-o] [![Closed PRs][🧮prs-c-img]][🧮prs-c] |
146
- | 3️⃣ | maintenance & linting | [![Helpers][🖇triage-help-img]][🖇triage-help] [![Depfu][🔑depfui]][🔑depfu] [![Contributors][🚎contributors-img]][🚎contributors] |
147
- | 4️⃣ | coverage & security | [![CodeCov][🖇codecov-img♻️]][🖇codecov] [![Coveralls][🏘coveralls-img]][🏘coveralls] [![Security Policy][🚎sec-pol-img]][🚎sec-pol] [![CodeQL][🖐codeQL-img]][🖐codeQL] |
148
- | 5️⃣ | resources | [![Get help on Codementor][🖇codementor-img]][🖇codementor] [![Chat][🏘chat-img]][🏘chat] [![Blog][🚎blog-img]][🚎blog] [![Wiki][🖐wiki-img]][🖐wiki] |
149
- | 6️⃣ | `...` 💖 | [![Liberapay Patrons][⛳liberapay-img]][⛳liberapay] [![Sponsor Me][🖇sponsor-img]][🖇sponsor] [![Follow Me on LinkedIn][🖇linkedin-img]][🖇linkedin] [![Find Me on WellFound:][✌️wellfound-img]][✌️wellfound] [![Find Me on CrunchBase][💲crunchbase-img]][💲crunchbase] [![My LinkTree][🌳linktree-img]][🌳linktree] [![Follow Me on Ruby.Social][🐘ruby-mast-img]][🐘ruby-mast] [![Tweet @ Peter][🐦tweet-img]][🐦tweet] [💻][coderme] [🌏][aboutme] |
150
-
151
- <!--
152
- The link tokens in the following sections should be kept ordered by the row and badge numbering scheme
153
- -->
154
-
155
- <!-- 1️⃣ name, license, docs -->
156
- [⛳️gem]: https://rubygems.org/gems/sanitize_email
157
- [⛳️name-img]: https://img.shields.io/badge/name-sanitize__email-brightgreen.svg?style=flat
158
- [🖇src-license]: https://opensource.org/licenses/MIT
159
- [🖇src-license-img]: https://img.shields.io/badge/License-MIT-green.svg
160
- [🚎yard]: https://www.rubydoc.info/gems/sanitize_email
161
- [🚎yard-img]: https://img.shields.io/badge/documentation-rubydoc-brightgreen.svg?style=flat
162
- [🧮semver]: http://semver.org/
163
- [🧮semver-img]: https://img.shields.io/badge/semver-2.0.0-FFDD67.svg?style=flat
164
- [📗keep-changelog]: https://keepachangelog.com/en/1.0.0/
165
- [📗keep-changelog-img]: https://img.shields.io/badge/keep--a--changelog-1.0.0-FFDD67.svg?style=flat
166
-
167
- <!-- 2️⃣ version & activity -->
168
- [⛳️version-img]: http://img.shields.io/gem/v/sanitize_email.svg
169
- [🖇DL-total-img]: https://img.shields.io/gem/dt/sanitize_email.svg
170
- [🏘DL-rank-img]: https://img.shields.io/gem/rt/sanitize_email.svg
171
- [🚎src-main]: https://gitlab.com/pboling/sanitize_email
172
- [🚎src-main-img]: https://img.shields.io/badge/source-gitlab-brightgreen.svg?style=flat
173
- [🖐prs-o]: https://gitlab.com/pboling/sanitize_email/-/merge_requests
174
- [🖐prs-o-img]: https://img.shields.io/github/issues-pr/pboling/sanitize_email
175
- [🧮prs-c]: https://github.com/pboling/sanitize_email/pulls?q=is%3Apr+is%3Aclosed
176
- [🧮prs-c-img]: https://img.shields.io/github/issues-pr-closed/pboling/sanitize_email
177
-
178
- <!-- 3️⃣ maintenance & linting -->
179
- [🖇triage-help]: https://www.codetriage.com/pboling/sanitize_email
180
- [🖇triage-help-img]: https://www.codetriage.com/pboling/sanitize_email/badges/users.svg
181
- [🚎contributors]: https://gitlab.com/pboling/sanitize_email/-/graphs/main
182
- [🚎contributors-img]: https://img.shields.io/github/contributors-anon/pboling/sanitize_email
183
-
184
- <!-- 4️⃣ coverage & security -->
185
- [🖇codecov-img♻️]: https://codecov.io/gh/pboling/sanitize_email/graph/badge.svg?token=Joire8DbSW
186
- [🖇codecov]: https://codecov.io/gh/pboling/sanitize_email
187
- [🏘coveralls]: https://coveralls.io/github/pboling/sanitize_email?branch=main
188
- [🏘coveralls-img]: https://coveralls.io/repos/github/pboling/sanitize_email/badge.svg?branch=main
189
- [🚎sec-pol]: https://gitlab.com/pboling/sanitize_email/-/blob/main/SECURITY.md
190
- [🚎sec-pol-img]: https://img.shields.io/badge/security-policy-brightgreen.svg?style=flat
191
- [🖐codeQL]: https://github.com/pboling/sanitize_email/security/code-scanning
192
- [🖐codeQL-img]: https://github.com/pboling/sanitize_email/actions/workflows/codeql-analysis.yml/badge.svg
193
-
194
- <!-- 5️⃣ resources -->
195
- [🖇codementor]: https://www.codementor.io/peterboling?utm_source=github&utm_medium=button&utm_term=peterboling&utm_campaign=github
196
- [🖇codementor-img]: https://cdn.codementor.io/badges/get_help_github.svg
197
- [🏘chat]: https://gitter.im/pboling/sanitize_email
198
- [🏘chat-img]: https://img.shields.io/gitter/room/pboling/sanitize_email.svg
199
- [🚎blog]: http://www.railsbling.com/tags/sanitize_email/
200
- [🚎blog-img]: https://img.shields.io/badge/blog-railsbling-brightgreen.svg?style=flat
201
- [🖐wiki]: https://gitlab.com/pboling/sanitize_email/-/wikis/home
202
- [🖐wiki-img]: https://img.shields.io/badge/wiki-examples-brightgreen.svg?style=flat
203
-
204
- <!-- 6️⃣ spread 💖 -->
205
- [🐦tweet-img]: https://img.shields.io/twitter/follow/galtzo.svg?style=social&label=Follow%20%40galtzo
206
- [🐦tweet]: http://twitter.com/galtzo
207
- [🚎blog]: http://www.railsbling.com/tags/sanitize_email/
208
- [🚎blog-img]: https://img.shields.io/badge/blog-railsbling-brightgreen.svg?style=flat
209
- [🖇linkedin]: http://www.linkedin.com/in/peterboling
210
- [🖇linkedin-img]: https://img.shields.io/badge/PeterBoling-blue?style=plastic&logo=linkedin
211
- [✌️wellfound]: https://angel.co/u/peter-boling
212
- [✌️wellfound-img]: https://img.shields.io/badge/peter--boling-orange?style=plastic&logo=wellfound
213
- [💲crunchbase]: https://www.crunchbase.com/person/peter-boling
214
- [💲crunchbase-img]: https://img.shields.io/badge/peter--boling-purple?style=plastic&logo=crunchbase
215
- [🐘ruby-mast]: https://ruby.social/@galtzo
216
- [🐘ruby-mast-img]: https://img.shields.io/mastodon/follow/109447111526622197?domain=https%3A%2F%2Fruby.social&style=plastic&logo=mastodon&label=Ruby%20%40galtzo
217
- [🌳linktree]: https://linktr.ee/galtzo
218
- [🌳linktree-img]: https://img.shields.io/badge/galtzo-purple?style=plastic&logo=linktree
219
-
220
- <!-- Maintainer Contact Links -->
221
- [aboutme]: https://about.me/peter.boling
222
- [coderme]: https://coderwall.com/Peter%20Boling
223
-
224
- ## Summary
27
+ ## 🌻 Synopsis
225
28
 
226
29
  It's particularly helpful when you want to prevent the delivery of email (e.g. in development/test environments) or alter the to/cc/bcc (e.g. in staging or demo environments) of all email generated from your application.
227
30
 
@@ -234,507 +37,483 @@ It's particularly helpful when you want to prevent the delivery of email (e.g. i
234
37
  * solves common problems in ruby web applications that use email
235
38
  * provides test helpers and spec matchers to assist with testing email content delivery
236
39
 
237
- ## Working Locally with Production Data
238
-
239
- 1. Have a production site with live data
240
- 2. Dump the live data and securely transfer it to another machine (e.g. rync -e ssh)
241
- 3. Import it into a development database
242
- 4. Test features which send out email (registration/signup, order placement, etc.)
243
- 5. Emails get sent (in real-life!) but to sanitized email recipients
244
- 6. Verify what they look like when sent
245
- 7. Iterate on email content design
246
- 8. No risk of emailing production addresses
247
-
248
- ## Re-routing Email on a Staging or QA Server
249
-
250
- Another very important use case for me is to transparently re-route email generated from a staging or QA server to an appropriate person. For example, it's common for us to set up a staging server for a client to use to view our progress and test out new features. It's important for any email that is generated from our web application be delivered to the client's inbox so that they can review the content and ensure that it's acceptable. `dotenv` or `direnv` allows each developer to configure the local behavior specifically for them via ENV vars.
251
-
252
- ## Testing Email from a Hot Production Server
253
-
254
- If you install this gem on a production server (which I don't always do), you can load up script/console and override the to/cc/bcc on all emails for the duration of your console session. This allows you to poke and prod a live production instance, and route all email to your own inbox for inspection. The best part is that this can all be accomplished without changing a single line of your application code.
255
-
256
- ## Monitoring all email sent by server to a backup account
257
-
258
- You may want to add a BCC automatically (e.g. to account-history@my-company.com) to every email sent by your system, for customer service purposes, and this gem allows that. Note that this may not be a good idea for all systems, for many reasons, e.g security!
259
-
260
- ## Using with a test suite as an alternative to the heavy email_spec
261
-
262
- [email_spec](https://github.com/bmabey/email-spec) is a great gem, with awesome rspec matchers and helpers, but it has an undeclared dependency on ActionMailer. Sad face.
263
-
264
- SanitizeEmail comes with some lightweight RspecMatchers covering most of what email_spec can do. It will help you test email functionality. It is useful when you are creating a gem to handle email features, or are writing a simple Ruby script, and don't want to pull in le Rails. SanitizeEmail has two dependencies, `mail` gem, and `version_gem`. Your Mail system just needs to conform to `mail` gem's `register_interceptor` API.
265
-
266
- ## Install Like a Boss
267
-
268
- In Gemfile:
269
-
270
- gem 'sanitize_email'
271
-
272
- Then:
40
+ ## 💡 Info you can shake a stick at
273
41
 
274
- bundle install
42
+ | Tokens to Remember | [![Gem name][⛳️name-img]][⛳️gem-name] [![Gem namespace][⛳️namespace-img]][⛳️gem-namespace] |
43
+ |-------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
44
+ | Works with JRuby | [![JRuby 9.2 Compat][💎jruby-9.2i]][🚎jruby-9.2-wf] [![JRuby 9.3 Compat][💎jruby-9.3i]][🚎jruby-9.3-wf] <br/> [![JRuby 9.4 Compat][💎jruby-9.4i]][🚎jruby-9.4-wf] [![JRuby current Compat][💎jruby-c-i]][🚎10-j-wf] [![JRuby HEAD Compat][💎jruby-headi]][🚎3-hd-wf]|
45
+ | Works with Truffle Ruby | [![Truffle Ruby 22.3 Compat][💎truby-22.3i]][🚎truby-22.3-wf] [![Truffle Ruby 23.0 Compat][💎truby-23.0i]][🚎truby-23.0-wf] [![Truffle Ruby 23.1 Compat][💎truby-23.1i]][🚎truby-23.1-wf] <br/> [![Truffle Ruby 24.2 Compat][💎truby-24.2i]][🚎truby-24.2-wf] [![Truffle Ruby 25.0 Compat][💎truby-25.0i]][🚎truby-25.0-wf] [![Truffle Ruby current Compat][💎truby-c-i]][🚎9-t-wf]|
46
+ | Works with MRI Ruby 4 | [![Ruby 4.0 Compat][💎ruby-4.0i]][🚎11-c-wf] [![Ruby current Compat][💎ruby-c-i]][🚎11-c-wf] [![Ruby HEAD Compat][💎ruby-headi]][🚎3-hd-wf]|
47
+ | Works with MRI Ruby 3 | [![Ruby 3.0 Compat][💎ruby-3.0i]][🚎ruby-3.0-wf] [![Ruby 3.1 Compat][💎ruby-3.1i]][🚎ruby-3.1-wf] [![Ruby 3.2 Compat][💎ruby-3.2i]][🚎ruby-3.2-wf] [![Ruby 3.3 Compat][💎ruby-3.3i]][🚎ruby-3.3-wf] [![Ruby 3.4 Compat][💎ruby-3.4i]][🚎ruby-3.4-wf]|
48
+ | Works with MRI Ruby 2 | [![Ruby 2.4 Compat][💎ruby-2.4i]][🚎ruby-2.4-wf] [![Ruby 2.5 Compat][💎ruby-2.5i]][🚎ruby-2.5-wf] [![Ruby 2.6 Compat][💎ruby-2.6i]][🚎ruby-2.6-wf] [![Ruby 2.7 Compat][💎ruby-2.7i]][🚎ruby-2.7-wf]|
49
+ | Support & Community | [![Join Me on Daily.dev's RubyFriends][✉️ruby-friends-img]][✉️ruby-friends] [![Live Chat on Discord][✉️discord-invite-img-ftb]][✉️discord-invite] [![Get help from me on Upwork][👨🏼‍🏫expsup-upwork-img]][👨🏼‍🏫expsup-upwork] [![Get help from me on Codementor][👨🏼‍🏫expsup-codementor-img]][👨🏼‍🏫expsup-codementor] |
50
+ | Source | [![Source on GitLab.com][📜src-gl-img]][📜src-gl] [![Source on CodeBerg.org][📜src-cb-img]][📜src-cb] [![Source on Github.com][📜src-gh-img]][📜src-gh] [![The best SHA: dQw4w9WgXcQ!][🧮kloc-img]][🧮kloc] |
51
+ | Documentation | [![Current release on RubyDoc.info][📜docs-cr-rd-img]][🚎yard-current] [![YARD on Galtzo.com][📜docs-head-rd-img]][🚎yard-head] [![Maintainer Blog][🚂maint-blog-img]][🚂maint-blog] [![GitLab Wiki][📜gl-wiki-img]][📜gl-wiki] [![GitHub Wiki][📜gh-wiki-img]][📜gh-wiki] |
52
+ | Compliance | [![License: MIT][📄license-img]][📄license] [![Apache license compatibility: Category A][📄license-compat-img]][📄license-compat] [![📄ilo-declaration-img]][📄ilo-declaration] [![Security Policy][🔐security-img]][🔐security] [![Contributor Covenant 2.1][🪇conduct-img]][🪇conduct] [![SemVer 2.0.0][📌semver-img]][📌semver] |
53
+ | Style | [![Enforced Code Style Linter][💎rlts-img]][💎rlts] [![Keep-A-Changelog 1.0.0][📗keep-changelog-img]][📗keep-changelog] [![Gitmoji Commits][📌gitmoji-img]][📌gitmoji] [![Compatibility appraised by: appraisal2][💎appraisal2-img]][💎appraisal2] |
54
+ | Maintainer 🎖️ | [![Follow Me on LinkedIn][💖🖇linkedin-img]][💖🖇linkedin] [![Follow Me on Ruby.Social][💖🐘ruby-mast-img]][💖🐘ruby-mast] [![Follow Me on Bluesky][💖🦋bluesky-img]][💖🦋bluesky] [![Contact Maintainer][🚂maint-contact-img]][🚂maint-contact] [![My technical writing][💖💁🏼‍♂️devto-img]][💖💁🏼‍♂️devto] |
55
+ | `...` 💖 | [![Find Me on WellFound:][💖✌️wellfound-img]][💖✌️wellfound] [![Find Me on CrunchBase][💖💲crunchbase-img]][💖💲crunchbase] [![My LinkTree][💖🌳linktree-img]][💖🌳linktree] [![More About Me][💖💁🏼‍♂️aboutme-img]][💖💁🏼‍♂️aboutme] [🧊][💖🧊berg] [🐙][💖🐙hub] [🛖][💖🛖hut] [🧪][💖🧪lab] |
275
56
 
276
- ## Setup with Ruby
57
+ ### Compatibility
277
58
 
278
- _keep scrolling for Rails, but read this for a better understanding of Magic_
59
+ Compatible with MRI Ruby 2.3.0+, and concordant releases of JRuby, and TruffleRuby.
60
+ CI workflows and Appraisals are generated for MRI Ruby 2.4+.
61
+ This test floor is configured by `ruby.test_minimum` in `.kettle-jem.yml` and
62
+ may be higher than the gem's runtime compatibility floor when legacy Rubies are
63
+ not practical for the current toolchain.
279
64
 
280
- There are three ways SanitizeEmail can be turned on; in order of precedence they are:
65
+ | 🚚 _Amazing_ test matrix was brought to you by | 🔎 appraisal2 🔎 and the color 💚 green 💚 |
66
+ |------------------------------------------------|--------------------------------------------------------|
67
+ | 👟 Check it out! | ✨ [github.com/appraisal-rb/appraisal2][💎appraisal2] ✨ |
281
68
 
282
- 1. Only useful for local context. Inside a method where you will be sending an email, set `SanitizeEmail.force_sanitize = true` just prior to delivering it. Also useful in the console.
283
69
 
284
- SanitizeEmail.force_sanitize = true # by default it is nil
285
70
 
286
- 2. If SanitizeEmail seems to not be sanitizing you have probably not registered the interceptor. SanitizeEmail tries to do this for you. *Note*: If you are working in an environment that has a Mail or Mailer class that uses the register_interceptor API, the interceptor will already have been registered by SanitizeEmail:
71
+ ### Federated DVCS
287
72
 
288
- # The gem will probably have already done this for you, but some really old versions of Rails may need you to do this manually:
289
- Mail.register_interceptor(SanitizeEmail::Bleach)
73
+ <details markdown="1">
74
+ <summary>Find this repo on federated forges (Coming soon!)</summary>
290
75
 
291
- Once registered, SanitizeEmail needs to be engaged:
76
+ | Federated [DVCS][💎d-in-dvcs] Repository | Status | Issues | PRs | Wiki | CI | Discussions |
77
+ |-------------------------------------------------|-----------------------------------------------------------------------|---------------------------|--------------------------|---------------------------|--------------------------|------------------------------|
78
+ | 🧪 [galtzo-floss/sanitize_email on GitLab][📜src-gl] | The Truth | [💚][🤝gl-issues] | [💚][🤝gl-pulls] | [💚][📜gl-wiki] | 🐭 Tiny Matrix | ➖ |
79
+ | 🧊 [galtzo-floss/sanitize_email on CodeBerg][📜src-cb] | An Ethical Mirror ([Donate][🤝cb-donate]) | [💚][🤝cb-issues] | [💚][🤝cb-pulls] | ➖ | ⭕️ No Matrix | ➖ |
80
+ | 🐙 [galtzo-floss/sanitize_email on GitHub][📜src-gh] | Another Mirror | [💚][🤝gh-issues] | [💚][🤝gh-pulls] | [💚][📜gh-wiki] | 💯 Full Matrix | [💚][gh-discussions] |
81
+ | 🎮️ [Discord Server][✉️discord-invite] | [![Live Chat on Discord][✉️discord-invite-img-ftb]][✉️discord-invite] | [Let's][✉️discord-invite] | [talk][✉️discord-invite] | [about][✉️discord-invite] | [this][✉️discord-invite] | [library!][✉️discord-invite] |
292
82
 
293
- # in config/initializers/sanitize_email.rb
294
- SanitizeEmail::Config.configure { |config| config[:engage] = true }
83
+ </details>
295
84
 
296
- 3. If you don't need to compute anything, then don't use this option, go with the previous option.
85
+ [gh-discussions]: https://github.com/galtzo-floss/sanitize_email/discussions
297
86
 
298
- SanitizeEmail::Config.configure { |config| config[:activation_proc] = proc { true } } # by default :activation_proc is false
87
+ ### Enterprise Support [![Tidelift](https://tidelift.com/badges/package/rubygems/sanitize_email)](https://tidelift.com/subscription/pkg/rubygems-sanitize_email?utm_source=rubygems-sanitize_email&utm_medium=referral&utm_campaign=readme)
299
88
 
300
- ### Examples
89
+ Available as part of the Tidelift Subscription.
301
90
 
302
- #### Only allow email to a specific domain
91
+ <details markdown="1">
92
+ <summary>Need enterprise-level guarantees?</summary>
303
93
 
304
- This works by ensuring that all recipients have the "allowed" domain.
305
- In other words, none of the recipients have a domain other than the allowed domain.
94
+ The maintainers of this and thousands of other packages are working with Tidelift to deliver commercial support and maintenance for the open source packages you use to build your applications. Save time, reduce risk, and improve code health, while paying the maintainers of the exact packages you use.
306
95
 
307
- allowed_domain = "example.com"
308
- # NOTE: you may need to check CC and BCC also, depending on your use case...
309
- SanitizeEmail::Config.configure do |config|
310
- config[:activation_proc] =
311
- ->(message) do
312
- !Array(message.to).any? { |recipient| Mail::Address.new(recipient).domain != allowed_domain }
313
- end
314
- end
96
+ [![Get help from me on Tidelift][🏙️entsup-tidelift-img]][🏙️entsup-tidelift]
315
97
 
316
- ### Notes
98
+ - 💡Subscribe for support guarantees covering _all_ your FLOSS dependencies
99
+ - 💡Tidelift is part of [Sonar][🏙️entsup-tidelift-sonar]
100
+ - 💡Tidelift pays maintainers to maintain the software you depend on!<br/>📊`@`Pointy Haired Boss: An [enterprise support][🏙️entsup-tidelift] subscription is "[never gonna let you down][🧮kloc]", and *supports* open source maintainers
317
101
 
318
- Number 1, above, is the method used by the SanitizeEmail.sanitary block.
319
- If installed but not configured, sanitize_email DOES NOTHING. Until configured the defaults leave it turned off.
102
+ Alternatively:
320
103
 
321
- ### Troubleshooting
104
+ - [![Live Chat on Discord][✉️discord-invite-img-ftb]][✉️discord-invite]
105
+ - [![Get help from me on Upwork][👨🏼‍🏫expsup-upwork-img]][👨🏼‍🏫expsup-upwork]
106
+ - [![Get help from me on Codementor][👨🏼‍🏫expsup-codementor-img]][👨🏼‍🏫expsup-codementor]
322
107
 
323
- IMPORTANT: You may need to setup your own register_interceptor. If sanitize_email doesn't seem to be working for you find your Mailer/Mail class and try this:
108
+ </details>
324
109
 
325
- # in config/initializers/sanitize_email.rb
326
- Mail.register_interceptor(SanitizeEmail::Bleach)
327
- SanitizeEmail::Config.configure { |config| config[:engage] = true }
110
+ ## Installation
328
111
 
329
- If that causes an error you will know why sanitize_email doesn't work.
330
- Otherwise it will start working according to the rest of the configuration.
112
+ Install the gem and add to the application's Gemfile by executing:
331
113
 
332
- ## Setup With Rails
114
+ ```console
115
+ bundle add sanitize_email
116
+ ```
333
117
 
334
- Create an initializer, if you are using rails, or otherwise configure:
118
+ If bundler is not being used to manage dependencies, install the gem by executing:
335
119
 
336
- SanitizeEmail::Config.configure do |config|
337
- config[:sanitized_to] = "to@sanitize_email.org"
338
- config[:sanitized_cc] = "cc@sanitize_email.org"
339
- config[:sanitized_bcc] = "bcc@sanitize_email.org"
340
- # run/call whatever logic should turn sanitize_email on and off in this Proc:
341
- config[:activation_proc] = proc { %w(development test).include?(Rails.env) }
342
- config[:use_actual_email_prepended_to_subject] = true # or false
343
- config[:use_actual_environment_prepended_to_subject] = true # or false
344
- config[:use_actual_email_as_sanitized_user_name] = true # or false
345
- end
120
+ ```console
121
+ gem install sanitize_email
122
+ ```
346
123
 
347
- Keep in mind, this is ruby (and possibly rails), so you can add conditionals or utilize different environment.rb files to customize these settings on a per-environment basis.
348
-
349
- ## Override the override
350
-
351
- But wait there's more:
352
-
353
- Let's say you have a method in your model that you can call to test the signup email. You want to be able to test sending it to any user at any time... but you don't want the user to ACTUALLY get the email, even in production. A dilemma, yes? Not anymore!
354
-
355
- To override the environment based switch use `force_sanitize`, which is normally `nil`, and ignored by default. When set to `true` or `false` it will turn sanitization on or off:
356
-
357
- SanitizeEmail.force_sanitize = true
358
-
359
- When testing your email in a console, you can manipulate how email will be handled in this way.
360
-
361
- There are also two methods that take a block and turn SanitizeEmail on or off (see section on Thread Safety below):
362
-
363
- Regardless of the Config settings of SanitizeEmail you can do a local override to force unsanitary email in any environment.
364
-
365
- SanitizeEmail.unsanitary do
366
- Mail.deliver do
367
- from "from@example.org"
368
- to "to@example.org" # Will actually be sent to the specified address, not sanitized
369
- reply_to "reply_to@example.org"
370
- subject "subject"
371
- end
372
- end
373
-
374
- Regardless of the Config settings of SanitizeEmail you can do a local override to send sanitary email in any environment.
375
- You have access to all the same configuration options in the parameter hash as you can set in the actual
376
- `SanitizeEmail.configure` block.
377
-
378
-
379
- SanitizeEmail.sanitary({sanitized_to: "boo@example.com"}) do # these config options are merged with the globals
380
- Mail.deliver do
381
- from "from@example.org"
382
- to "to@example.org" # Will actually be sent to the override addresses, in this case: boo@example.com
383
- reply_to "reply_to@example.org"
384
- subject "subject"
385
- end
386
- end
387
-
388
- ## Configuration Options
124
+ ## ⚙️ Configuration
389
125
 
390
126
  As used in the "Description" column below, `engaged` means: `SanitizeEmail.activate?(message) # => true`.
391
127
  This happens in a few different ways, and two of them are in the config below (`engage` and `activation_proc`).
392
128
 
393
- | Option | Type (Yard format) | Description |
394
- |---------------------------------------------|--------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------|
395
- | sanitized_to | [String, Array[String]] | (when engaged) Override CC field with these addresses |
396
- | sanitized_cc | [String, Array[String]] | (when engaged) Override CC field with these addresses |
397
- | sanitized_bcc | [String, Array[String]] | (when engaged) Override BCC field with these addresses |
398
- | good_list | [Array[String]] | (when engaged) Email addresses to allow to pass-through without overriding |
399
- | bad_list | [Array[String]] | (when engaged) Email addresses to be removed from message's TO, CC, & BCC |
400
- | environment | [String, #to_s, Proc, Lambda, #call] | (when engaged) The environment value to use wherever it is added to message (e.g. in the subject line) |
401
- | use_actual_email_as_sanitized_user_name | [Boolean] | (when engaged) Use "real" email address as username for sanitized email address (e.g. "real at example.com <sanitized@example.com>") |
402
- | use_actual_email_prepended_to_subject | [Boolean] | (when engaged) Use "real" email address prepended to subject (e.g. "real at example.com Original Subject") |
403
- | use_actual_environment_prepended_to_subject | [Boolean] | (when engaged) Use `environment` prepended to subject (e.g. "{{ STAGING }} Original Subject") |
404
- | engage | [Boolean, nil] | Boolean will turn engage or disengage this gem, while `nil` ignores this setting and instead checks `activation_proc` |
405
- | activation_proc | [Proc, Lambda, #call] | When checked, due to `engage: nil`, the result will either engage or disengage this gem |
406
-
407
- ## Thread Safety
408
-
409
- So long as you don't change the config after initializing it at runtime, you'll be fine.
410
- Like many Ruby tools' config objects, it is a single config object, shared by all threads.
411
- The helpers like `sanitary`, `unsanitary`, `janitor`, and `force_sanitize`
412
- are intended to be used in single threaded environments,
413
- like a test suite, or a console session.
414
-
415
- I doubt I'll ever have a need for runtime reconfiguration of the config,
416
- so I doubt I'll ever have a reason to make it "more" thread safe than it is now, but PRs are welcome!
417
-
418
- ## Use sanitize_email in your test suite!
419
-
420
- ### rspec
421
-
422
- In your `spec_helper.rb`:
423
-
424
-
425
- require "sanitize_email"
426
- # rspec matchers are *not* loaded by default in sanitize_email, as it is not primarily a gem for test suites.
427
- require "sanitize_email/rspec_matchers"
428
-
429
- SanitizeEmail::Config.configure do |config|
430
- config[:sanitized_to] = "sanitize_email@example.org"
431
- config[:sanitized_cc] = "sanitize_email@example.org"
432
- config[:sanitized_bcc] = "sanitize_email@example.org"
433
- # run/call whatever logic should turn sanitize_email on and off in this Proc.
434
- # config[:activation_proc] = Proc.new { true }
435
- # Since this configuration is *inside* the spec_helper, it might be assumed that we always want to sanitize. If we don't want to it can be easily manipulated with SanitizeEmail.unsanitary and SanitizeEmail.sanitary block helpers.
436
- # Thus instead of using the Proc (slower) we just engage it always:
437
- config[:engage] = true
438
- config[:use_actual_email_prepended_to_subject] = true # or false
439
- config[:use_actual_environment_prepended_to_subject] = true # or false
440
- config[:use_actual_email_as_sanitized_user_name] = true # or false
441
- end
442
-
443
- # If your mail system is not one that sanitize_email automatically configures an interceptor for (ActionMailer, Mail)
444
- # then you will need to do the equivalent for whatever Mail system you are using.
445
-
446
- RSpec.configure do |config|
447
- # ...
448
- # From sanitize_email gem
449
- config.include(SanitizeEmail::RspecMatchers)
450
- end
451
-
452
- context "an email test" do
453
- subject { Mail.deliver(@message_hash) }
454
- it { should have_to("sanitize_email@example.org") }
455
- end
456
-
457
- #### have_* matchers
458
-
459
- These will look for an email address in any of the following mail attributes:
460
-
461
- [:from, :to, :cc, :bcc, :subject, :reply_to]
462
-
463
- Example:
129
+ | Option | Type (Yard format) | Description |
130
+ |---------------------------------------------|--------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------|
131
+ | sanitized_to | [String, Array[String]] | (when engaged) Override CC field with these addresses |
132
+ | sanitized_cc | [String, Array[String]] | (when engaged) Override CC field with these addresses |
133
+ | sanitized_bcc | [String, Array[String]] | (when engaged) Override BCC field with these addresses |
134
+ | good_list | [Array[String]] | (when engaged) Email addresses to allow to pass-through without overriding |
135
+ | bad_list | [Array[String]] | (when engaged) Email addresses to be removed from message's TO, CC, & BCC |
136
+ | environment | [String, #to_s, Proc, Lambda, #call] | (when engaged) The environment value to use wherever it is added to message (e.g. in the subject line) |
137
+ | use_actual_email_as_sanitized_user_name | [Boolean] | (when engaged) Use "real" email address as username for sanitized email address (e.g. `"real at example.com <sanitized@example.com>"`) |
138
+ | use_actual_email_prepended_to_subject | [Boolean] | (when engaged) Use "real" email address prepended to subject (e.g. `"real at example.com Original Subject"`) |
139
+ | use_actual_environment_prepended_to_subject | [Boolean] | (when engaged) Use `environment` prepended to subject (e.g. `"[[ STAGING ]] Original Subject"`) |
140
+ | engage | [Boolean, nil] | Boolean will turn engage or disengage this gem, while `nil` ignores this setting and instead checks `activation_proc` |
141
+ | activation_proc | [Proc, Lambda, #call] | When checked, due to `engage: nil`, the result will either engage or disengage this gem |
464
142
 
465
- context "the subject line must have the email address sanitize_email@example.org" do
466
- subject { Mail.deliver(@message_hash) }
467
- it { should have_subject("sanitize_email@example.org") }
468
- end
143
+ ## 🔧 Basic Usage
469
144
 
470
- #### be_* matchers
471
145
 
472
- These will look for a matching string in any of the following attributes:
146
+ ## 🦷 FLOSS Funding
473
147
 
474
- [:from, :to, :cc, :bcc, :subject, :reply_to]
148
+ While pboling tools are free software and will always be, the project would benefit immensely from some funding.
149
+ Raising a monthly budget of... "dollars" would make the project more sustainable.
475
150
 
476
- Example:
151
+ We welcome both individual and corporate sponsors! We also offer a
152
+ wide array of funding channels to account for your preferences.
153
+ Currently, [GitHub Sponsors][🖇sponsor], and [Liberapay][⛳liberapay] are our preferred funding platforms.
477
154
 
478
- context "the subject line must have the string 'foobarbaz'" do
479
- subject { Mail.deliver(@message_hash) }
480
- it { should be_subject("foobarbaz") }
481
- end
155
+ **If you're working in a company that's making significant use of pboling tools we'd
156
+ appreciate it if you suggest to your company to become a pboling sponsor.**
482
157
 
483
- #### have_to_username matcher
158
+ You can support the development of pboling tools via
159
+ [GitHub Sponsors][🖇sponsor],
160
+ [Liberapay][⛳liberapay],
161
+ [PayPal][🖇paypal],
162
+ and [Tidelift][🏙️entsup-tidelift].
484
163
 
485
- The `username` in the `:to` field is when the `:to` field is formatted like this:
164
+ | 📍 NOTE |
165
+ |----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
166
+ | If doing a sponsorship in the form of donation is problematic for your company <br/> from an accounting standpoint, we'd recommend the use of Tidelift, <br/> where you can get a support-like subscription instead. |
486
167
 
487
- `"Peter Boling" <sanitize_email@example.org>`
488
168
 
489
- Example:
169
+ ### Another way to support open-source
490
170
 
491
- context "the to field must have the username 'Peter Boling'" do
492
- subject { Mail.deliver(@message_hash) }
493
- it { should have_to_username("Peter Boling") }
494
- end
171
+ I’m driven by a passion to foster a thriving open-source community – a space where people can tackle complex problems, no matter how small. Revitalizing libraries that have fallen into disrepair, and building new libraries focused on solving real-world challenges, are my passions. I was recently affected by layoffs, and the tech jobs market is unwelcoming. I’m reaching out here because your support would significantly aid my efforts to provide for my family, and my farm (11 🐔 chickens, 2 🐶 dogs, 3 🐰 rabbits, 8 🐈‍ cats).
495
172
 
496
- #### have_sanitized_to_header matcher
173
+ If you work at a company that uses my work, please encourage them to support me as a corporate sponsor. My work on gems you use might show up in `bundle fund`.
497
174
 
498
- Matches any part of the value of the first sanitized to header (`"X-Sanitize-Email-To"`),
499
- which could be formatted like this:
175
+ I’m developing a new library, [floss_funding][🖇floss-funding-gem], designed to empower open-source developers like myself to get paid for the work we do, in a sustainable way. Please give it a look.
500
176
 
501
- `"Peter Boling" <sanitize_email@example.org>`
177
+ **[Floss-Funding.dev][🖇floss-funding.dev]: 👉️ No network calls. 👉️ No tracking. 👉️ No oversight. 👉️ Minimal crypto hashing. 💡 Easily disabled nags**
502
178
 
503
- NOTE: It won't match subsequent headers like `"X-Sanitize-Email-To-2"`, or `"X-Sanitize-Email-To-3"`.
179
+ [![Sponsor Me on Github][🖇sponsor-img]][🖇sponsor] [![Liberapay Goal Progress][⛳liberapay-img]][⛳liberapay] [![Donate on PayPal][🖇paypal-img]][🖇paypal] [![Buy me a coffee][🖇buyme-small-img]][🖇buyme] [![Donate on Polar][🖇polar-img]][🖇polar] [![Donate to my FLOSS efforts at ko-fi.com][🖇kofi-img]][🖇kofi] [![Donate to my FLOSS efforts using Patreon][🖇patreon-img]][🖇patreon]
504
180
 
505
- Example:
181
+ ## 🔐 Security
506
182
 
507
- context "the first 'X-Sanitize-Email-To' header must have the username 'Peter Boling'" do
508
- subject { Mail.deliver(@message_hash) }
509
- it { should have_sanitized_to_header("Peter Boling") }
510
- end
183
+ See [SECURITY.md][🔐security].
511
184
 
512
- #### have_cc_username matcher
513
-
514
- The `username` in the `:cc` field is when the `:c` field is formatted like this:
515
-
516
- `"Peter Boling" <sanitize_email@example.org>`
517
-
518
- Example:
519
-
520
- context "the cc field must have the username 'Peter Boling'" do
521
- subject { Mail.deliver(@message_hash) }
522
- it { should have_cc_username("Peter Boling") }
523
- end
524
-
525
- #### have_sanitized_cc_header matcher
526
-
527
- Matches any part of the value of the first sanitized cc header (`"X-Sanitize-Email-Cc"`),
528
- which could be formatted like this:
529
-
530
- `"Peter Boling" <sanitize_email@example.org>`
531
-
532
- NOTE: It won't match subsequent headers like `"X-Sanitize-Email-Cc-2"`, or `"X-Sanitize-Email-Cc-3"`.
533
-
534
- Example:
535
-
536
- context "the first 'X-Sanitize-Email-Cc' header must have the username 'Peter Boling'" do
537
- subject { Mail.deliver(@message_hash) }
538
- it { should have_sanitized_cc_header("Peter Boling") }
539
- end
540
-
541
- ### non-rspec (Test::Unit, mini-test, etc)
542
-
543
- In your setup file:
544
-
545
- require "sanitize_email"
546
- # test helpers are *not* loaded by default in sanitize_email, as it is not primarily a gem for test suites.
547
- require "sanitize_email/test_helpers"
548
-
549
- SanitizeEmail::Config.configure do |config|
550
- config[:sanitized_to] = "sanitize_email@example.org"
551
- config[:sanitized_cc] = "sanitize_email@example.org"
552
- config[:sanitized_bcc] = "sanitize_email@example.org"
553
- # run/call whatever logic should turn sanitize_email on and off in this Proc.
554
- # config[:activation_proc] = Proc.new { true }
555
- # Since this configuration is *inside* the spec_helper, it might be assumed that we always want to sanitize. If we don't want to it can be easily manipulated with SanitizeEmail.unsanitary and SanitizeEmail.sanitary block helpers.
556
- # Thus instead of using the Proc (slower) we just engage it always:
557
- config[:engage] = true
558
- config[:use_actual_email_prepended_to_subject] = true # or false
559
- config[:use_actual_environment_prepended_to_subject] = true # or false
560
- config[:use_actual_email_as_sanitized_user_name] = true # or false
561
- end
562
-
563
- # If your mail system is not one that sanitize_email automatically configures an interceptor for (ActionMailer, Mail)
564
- # then you will need to do the equivalent for whatever Mail system you are using.
565
-
566
- # You need to know what to do here... somehow get the methods into rhw scope of your tests.
567
- # Something like this maybe?
568
- include SanitizeEmail::TestHelpers
569
- # Look here to see what it gives you:
570
- # https://github.com/pboling/sanitize_email/blob/master/lib/sanitize_email/test_helpers.rb
571
-
572
- ## Deprecations
573
-
574
- Sometimes things get deprecated (meaning they still work, but are noisy about it). If this happens to you, and you like your head in the sand, call this number:
185
+ ## 🤝 Contributing
575
186
 
576
- SanitizeEmail::Deprecation.deprecate_in_silence = true
187
+ If you need some ideas of where to help, you could work on adding more code coverage,
188
+ or if it is already 💯 (see [below](#code-coverage)) check [issues][🤝gh-issues] or [PRs][🤝gh-pulls],
189
+ or use the gem and think about how it could be better.
577
190
 
578
- ## Authors
191
+ We [![Keep A Changelog][📗keep-changelog-img]][📗keep-changelog] so if you make changes, remember to update it.
579
192
 
580
- Peter Boling is the original author of the code, and current maintainer.
193
+ See [CONTRIBUTING.md][🤝contributing] for more detailed instructions.
581
194
 
582
- Thanks to John Trupiano for turning Peter's original Rails plugin into the initial cut of this gem!
195
+ ### 🚀 Release Instructions
583
196
 
584
- ## 🤝 Contributing
197
+ See [CONTRIBUTING.md][🤝contributing].
585
198
 
586
- See [CONTRIBUTING.md][🤝contributing]
199
+ ### Code Coverage
587
200
 
588
- [🤝contributing]: CONTRIBUTING.md
201
+ <details markdown="1">
202
+ <summary>Coverage service badges</summary>
589
203
 
590
- ### You can help!
204
+ [![Coverage Graph][🏀codecov-g]][🏀codecov]
591
205
 
592
- Take a look at the `reek` list which is the file called `REEK` and start fixing things.
206
+ [![Coveralls Test Coverage][🏀coveralls-img]][🏀coveralls]
593
207
 
594
- To refresh the `reek` list:
208
+ [![QLTY Test Coverage][🏀qlty-covi]][🏀qlty-cov]
595
209
 
596
- `bundle exec reek > REEK`
210
+ </details>
597
211
 
598
- Then follow these instructions:
212
+ ### 🪇 Code of Conduct
599
213
 
600
- 1. Fork the repository
601
- 2. Create your feature branch (`git checkout -b my-new-feature`)
602
- 3. Make some fixes.
603
- 4. Commit your changes (`git commit -am 'Added some feature'`)
604
- 5. Push to the branch (`git push origin my-new-feature`)
605
- 6. Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
606
- 7. Create new Pull Request.
214
+ Everyone interacting with this project's codebases, issue trackers,
215
+ chat rooms and mailing lists agrees to follow the [![Contributor Covenant 2.1][🪇conduct-img]][🪇conduct].
607
216
 
608
217
  ## 🌈 Contributors
609
218
 
610
- [![Contributors][🌈contrib-rocks-img]][🐙hub-contrib]
611
-
612
- Contributor tiles (GitHub only) made with [contributors-img][🌈contrib-rocks].
613
-
614
- Learn more about, or become one of, our 🎖 contributors on:
219
+ [![Contributors][🖐contributors-img]][🖐contributors]
615
220
 
616
- | Any | Of | These | DVCS |
617
- |-------------------------------------|---------------------------------------|-------------------------------------|-------------------------------------|
618
- | [🐙hub contributors][🐙hub-contrib] | [🧊berg contributors][🧊berg-contrib] | [🛖hut contributors][🛖hut-contrib] | [🧪lab contributors][🧪lab-contrib] |
221
+ Made with [contributors-img][🖐contrib-rocks].
619
222
 
620
- [comment]: <> ( DVCS CONTRIB LINKS )
223
+ Also see GitLab Contributors: [https://gitlab.com/galtzo-floss/sanitize_email/-/graphs/main][🚎contributors-gl]
621
224
 
622
- [🌈contrib-rocks]: https://contrib.rocks
623
- [🌈contrib-rocks-img]: https://contrib.rocks/image?repo=pboling/sanitize_email
225
+ <details>
226
+ <summary>⭐️ Star History</summary>
624
227
 
625
- [🧊berg-contrib]: https://codeberg.org/pboling/sanitize_email/activity
626
- [🐙hub-contrib]: https://github.com/pboling/sanitize_email/graphs/contributors
627
- [🛖hut-contrib]: https://git.sr.ht/~galtzo/sanitize_email/log/
628
- [🧪lab-contrib]: https://gitlab.com/pboling/sanitize_email/-/graphs/main?ref_type=heads
629
-
630
- ## Star History
631
-
632
- <a href="https://star-history.com/#pboling/sanitize_email&Date">
228
+ <a href="https://star-history.com/galtzo-floss/sanitize_email&Date">
633
229
  <picture>
634
- <source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/svg?repos=pboling/sanitize_email&type=Date&theme=dark" />
635
- <source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/svg?repos=pboling/sanitize_email&type=Date" />
636
- <img alt="Star History Chart" src="https://api.star-history.com/svg?repos=pboling/sanitize_email&type=Date" />
230
+ <source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/svg?repos=galtzo-floss/sanitize_email&type=Date&theme=dark" />
231
+ <source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/svg?repos=galtzo-floss/sanitize_email&type=Date" />
232
+ <img alt="Star History Chart" src="https://api.star-history.com/svg?repos=galtzo-floss/sanitize_email&type=Date" />
637
233
  </picture>
638
234
  </a>
639
235
 
640
- ## Running Specs
641
-
642
- The basic compatibility matrix:
643
-
644
- appraisal install
645
- appraisal rake test
646
-
647
- NOTE: `appraisal install` uses the standard Gemfile, and thus adds a bunch of gems
648
- we do not need in each of our appraisal gemfiles.
649
-
650
- Instead we can do one of:
651
-
652
- BUNDLE_GEMFILE=gemfiles/vanilla.gemfile appraisal generate
653
- BUNDLE_GEMFILE=gemfiles/vanilla.gemfile appraisal update
236
+ </details>
654
237
 
655
- NOTE: This results in bad paths to the gemspec from each of the appraisal `gemfiles/rails_*_*.gemfile` files.
656
- `gemspec path: "../../"` needs to be replaced with `gemspec path: "../"` in each Appraisal gemfile.
657
-
658
- It is unlikely to be possible to install all of the supported Rubies & Railsies in a single container...
659
- See the various github action workflows for more inspiration on running certain oldies.
660
-
661
- ### Code Coverage
662
-
663
- [![Coverage Graph][🔑codecov-g]][🖇codecov]
664
-
665
- [🔑codecov-g]: https://codecov.io/gh/pboling/sanitize_email/graphs/tree.svg?token=Joire8DbSW
238
+ ## 📌 Versioning
666
239
 
667
- ## 🪇 Code of Conduct
240
+ This library follows [![Semantic Versioning 2.0.0][📌semver-img]][📌semver] for its public API where practical.
241
+ For most applications, prefer the [Pessimistic Version Constraint][📌pvc] with two digits of precision.
668
242
 
669
- Everyone interacting in this project's codebases, issue trackers,
670
- chat rooms and mailing lists is expected to follow the [code of conduct][🪇conduct].
243
+ For example:
671
244
 
672
- [🪇conduct]: CODE_OF_CONDUCT.md
245
+ ```ruby
246
+ spec.add_dependency("sanitize_email", "~> 2.0")
247
+ ```
673
248
 
674
- ## 📌 Versioning
249
+ <details markdown="1">
250
+ <summary>📌 Is "Platform Support" part of the public API? More details inside.</summary>
675
251
 
676
- This Library adheres to [Semantic Versioning 2.0.0][📌semver].
677
- Violations of this scheme should be reported as bugs.
678
- Specifically, if a minor or patch version is released that breaks backward compatibility,
679
- a new version should be immediately released that restores compatibility.
680
- Breaking changes to the public API will only be introduced with new major versions.
252
+ Dropping support for a platform can be a breaking change for affected users.
253
+ If a release changes supported platforms, it should be called out clearly in the changelog and versioned with that impact in mind.
681
254
 
682
255
  To get a better understanding of how SemVer is intended to work over a project's lifetime,
683
256
  read this article from the creator of SemVer:
684
257
 
685
258
  - ["Major Version Numbers are Not Sacred"][📌major-versions-not-sacred]
686
259
 
687
- As a result of this policy, you can (and should) specify a dependency on these libraries using
688
- the [Pessimistic Version Constraint][📌pvc] with two digits of precision.
260
+ </details>
689
261
 
690
- For example:
262
+ See [CHANGELOG.md][📌changelog] for a list of releases.
691
263
 
692
- spec.add_dependency("sanitize_email", "~> 2.0")
264
+ ## 📄 License
693
265
 
694
- [comment]: <> ( 📌 VERSIONING LINKS )
266
+ The gem is available as open source under the terms of
267
+ the [MIT](MIT.md) [![License: MIT][📄license-img]][📄license-ref].
695
268
 
696
- [📌pvc]: http://guides.rubygems.org/patterns/#pessimistic-version-constraint
697
- [📌semver]: http://semver.org/
698
- [📌major-versions-not-sacred]: https://tom.preston-werner.com/2022/05/23/major-version-numbers-are-not-sacred.html
269
+ ### © Copyright
699
270
 
700
- ## References
271
+ See [LICENSE.md][📄license] for the official copyright notice.
701
272
 
702
- * [Source Code](http://github.com/pboling/sanitize_email)
703
- * [Gem Release Announcement](http://blog.smartlogicsolutions.com/2009/04/25/reintroducing-sanitize_email-work-with-production-email-without-fear/)
704
- * [Peter's Original Writeup](http://galtzo.blogspot.com/2008/11/sanitize-email-never-worry-about.html)
705
- * [Using sanitize_email to Preview HTML Emails Locally](http://blog.smartlogicsolutions.com/2009/04/30/using-sanitize-email-to-preview-html-emails-locally/)
273
+ <details markdown="1">
274
+ <summary>Copyright holders</summary>
706
275
 
707
- ## 📄 License
276
+ - Copyright (c) 2008 Peter Boling
277
+ - Copyright (c) 2009 John Trupiano
278
+ - Copyright (c) 2009-2010 pboling
279
+ - Copyright (c) 2009 Peter H. Boling
280
+ - Copyright (c) 2012 David Morton
281
+ - Copyright (c) 2012 Harry Lascelles
282
+ - Copyright (c) 2012-2018, 2022, 2024, 2026 Peter H. Boling
283
+ - Copyright (c) 2013 Adrien Siami
284
+ - Copyright (c) 2013 Chris Altman
285
+ - Copyright (c) 2014 Scott Rocher
286
+ - Copyright (c) 2017 Marcus Ilgner
287
+ - Copyright (c) 2018 Bernardo Galindo
288
+ - Copyright (c) 2024-2025 joeyparis
708
289
 
709
- The gem is available as open source under the terms of
710
- the [MIT License][📄license] [![License: MIT][📄license-img]][📄license-ref].
711
- See [LICENSE.txt][📄license] for the official [Copyright Notice][📄copyright-notice-explainer].
290
+ </details>
712
291
 
713
- [comment]: <> ( 📄 LEGAL LINKS )
292
+ ## 🤑 A request for help
714
293
 
715
- [📄copyright-notice-explainer]: https://opensource.stackexchange.com/questions/5778/why-do-licenses-such-as-the-mit-license-specify-a-single-year
716
- [📄license]: LICENSE.txt
717
- [📄license-ref]: https://opensource.org/licenses/MIT
718
- [📄license-img]: https://img.shields.io/badge/License-MIT-green.svg
294
+ Maintainers have teeth and need to pay their dentists.
295
+ After getting laid off in an RIF in March, and encountering difficulty finding a new one,
296
+ I began spending most of my time building open source tools.
297
+ I'm hoping to be able to pay for my kids' health insurance this month,
298
+ so if you value the work I am doing, I need your support.
299
+ Please consider sponsoring me or the project.
719
300
 
720
- ### © Copyright
301
+ To join the community or get help 👇️ Join the Discord.
721
302
 
722
- * Copyright (c) 2009 [John Trupiano](http://smartlogicsolutions.com/wiki/John_Trupiano) of [SmartLogic Solutions, LLC](http://www.smartlogicsolutions.com)
723
- * Copyright (c) 2008 - 2018, 2020, 2022, 2024 [Peter H. Boling][peterboling] of [Rails Bling][railsbling]
303
+ [![Live Chat on Discord][✉️discord-invite-img-ftb]][✉️discord-invite]
724
304
 
725
- [railsbling]: http://www.railsbling.com
726
- [peterboling]: http://www.peterboling.com
305
+ To say "thanks!" ☝️ Join the Discord or 👇️ send money.
727
306
 
728
- ## 🤑 One more thing
307
+ [![Sponsor me on GitHub Sponsors][🖇sponsor-bottom-img]][🖇sponsor] 💌 [![Sponsor me on Liberapay][⛳liberapay-bottom-img]][⛳liberapay] 💌 [![Donate on PayPal][🖇paypal-bottom-img]][🖇paypal]
729
308
 
730
- You made it to the bottom of the page,
731
- so perhaps you'll indulge me for another 20 seconds.
732
- I maintain many dozens of gems, including this one,
733
- because I want Ruby to be a great place for people to solve problems, big and small.
734
- Please consider supporting my efforts via the giant yellow link below,
735
- or one of the others at the head of this README.
309
+ ### Please give the project a star ⭐ ♥.
736
310
 
737
- [![Buy me a latte][🖇buyme-img]][🖇buyme]
311
+ Thanks for RTFM. ☺️
738
312
 
313
+ [⛳liberapay-img]: https://img.shields.io/liberapay/goal/pboling.svg?logo=liberapay&color=a51611&style=flat
314
+ [⛳liberapay-bottom-img]: https://img.shields.io/liberapay/goal/pboling.svg?style=for-the-badge&logo=liberapay&color=a51611
315
+ [⛳liberapay]: https://liberapay.com/pboling/donate
316
+ [🖇sponsor-img]: https://img.shields.io/badge/Sponsor_Me!-pboling.svg?style=social&logo=github
317
+ [🖇sponsor-bottom-img]: https://img.shields.io/badge/Sponsor_Me!-pboling-blue?style=for-the-badge&logo=github
318
+ [🖇sponsor]: https://github.com/sponsors/pboling
319
+ [🖇polar-img]: https://img.shields.io/badge/polar-donate-a51611.svg?style=flat
320
+ [🖇polar]: https://polar.sh/pboling
321
+ [🖇kofi-img]: https://img.shields.io/badge/ko--fi-%E2%9C%93-a51611.svg?style=flat
322
+ [🖇kofi]: https://ko-fi.com/pboling
323
+ [🖇patreon-img]: https://img.shields.io/badge/patreon-donate-a51611.svg?style=flat
324
+ [🖇patreon]: https://patreon.com/galtzo
325
+ [🖇buyme-small-img]: https://img.shields.io/badge/buy_me_a_coffee-%E2%9C%93-a51611.svg?style=flat
739
326
  [🖇buyme-img]: https://img.buymeacoffee.com/button-api/?text=Buy%20me%20a%20latte&emoji=&slug=pboling&button_colour=FFDD00&font_colour=000000&font_family=Cookie&outline_colour=000000&coffee_colour=ffffff
740
327
  [🖇buyme]: https://www.buymeacoffee.com/pboling
328
+ [🖇paypal-img]: https://img.shields.io/badge/donate-paypal-a51611.svg?style=flat&logo=paypal
329
+ [🖇paypal-bottom-img]: https://img.shields.io/badge/donate-paypal-a51611.svg?style=for-the-badge&logo=paypal&color=0A0A0A
330
+ [🖇paypal]: https://www.paypal.com/paypalme/peterboling
331
+ [🖇floss-funding.dev]: https://floss-funding.dev
332
+ [🖇floss-funding-gem]: https://github.com/galtzo-floss/floss_funding
333
+ [✉️discord-invite]: https://discord.gg/3qme4XHNKN
334
+ [✉️discord-invite-img-ftb]: https://img.shields.io/discord/1373797679469170758?style=for-the-badge&logo=discord
335
+ [✉️ruby-friends-img]: https://img.shields.io/badge/daily.dev-%F0%9F%92%8E_Ruby_Friends-0A0A0A?style=for-the-badge&logo=dailydotdev&logoColor=white
336
+ [✉️ruby-friends]: https://app.daily.dev/squads/rubyfriends
337
+
338
+ [✇bundle-group-pattern]: https://gist.github.com/pboling/4564780
339
+ [⛳️gem-namespace]: https://github.com/galtzo-floss/sanitize_email/tree/main/gems/sanitize_email
340
+ [⛳️namespace-img]: https://img.shields.io/badge/namespace-SanitizeEmail-3C2D2D.svg?style=square&logo=ruby&logoColor=white
341
+ [⛳️gem-name]: https://bestgems.org/gems/sanitize_email
342
+ [⛳️name-img]: https://img.shields.io/badge/name-sanitize__email-3C2D2D.svg?style=square&logo=rubygems&logoColor=red
343
+ [⛳️tag-img]: https://img.shields.io/github/tag/galtzo-floss/sanitize_email.svg
344
+ [⛳️tag]: https://github.com/galtzo-floss/sanitize_email/releases
345
+ [🚂maint-blog]: http://www.railsbling.com/tags/sanitize_email
346
+ [🚂maint-blog-img]: https://img.shields.io/badge/blog-railsbling-0093D0.svg?style=for-the-badge&logo=rubyonrails&logoColor=orange
347
+ [🚂maint-contact]: http://www.railsbling.com/contact
348
+ [🚂maint-contact-img]: https://img.shields.io/badge/Contact-Maintainer-0093D0.svg?style=flat&logo=rubyonrails&logoColor=red
349
+ [💖🖇linkedin]: http://www.linkedin.com/in/peterboling
350
+ [💖🖇linkedin-img]: https://img.shields.io/badge/LinkedIn-Profile-0B66C2?style=flat&logo=newjapanprowrestling
351
+ [💖✌️wellfound]: https://wellfound.com/u/peter-boling
352
+ [💖✌️wellfound-img]: https://img.shields.io/badge/peter--boling-orange?style=flat&logo=wellfound
353
+ [💖💲crunchbase]: https://www.crunchbase.com/person/peter-boling
354
+ [💖💲crunchbase-img]: https://img.shields.io/badge/peter--boling-purple?style=flat&logo=crunchbase
355
+ [💖🐘ruby-mast]: https://ruby.social/@galtzo
356
+ [💖🐘ruby-mast-img]: https://img.shields.io/mastodon/follow/109447111526622197?domain=https://ruby.social&style=flat&logo=mastodon&label=Ruby%20@galtzo
357
+ [💖🦋bluesky]: https://bsky.app/profile/galtzo.com
358
+ [💖🦋bluesky-img]: https://img.shields.io/badge/@galtzo.com-0285FF?style=flat&logo=bluesky&logoColor=white
359
+ [💖🌳linktree]: https://linktr.ee/galtzo
360
+ [💖🌳linktree-img]: https://img.shields.io/badge/galtzo-purple?style=flat&logo=linktree
361
+ [💖💁🏼‍♂️devto]: https://dev.to/galtzo
362
+ [💖💁🏼‍♂️devto-img]: https://img.shields.io/badge/dev.to-0A0A0A?style=flat&logo=devdotto&logoColor=white
363
+ [💖💁🏼‍♂️aboutme]: https://about.me/peter.boling
364
+ [💖💁🏼‍♂️aboutme-img]: https://img.shields.io/badge/about.me-0A0A0A?style=flat&logo=aboutme&logoColor=white
365
+ [💖🧊berg]: https://codeberg.org/pboling
366
+ [💖🐙hub]: https://github.org/pboling
367
+ [💖🛖hut]: https://sr.ht/~galtzo/
368
+ [💖🧪lab]: https://gitlab.com/pboling
369
+ [👨🏼‍🏫expsup-upwork]: https://www.upwork.com/freelancers/~014942e9b056abdf86?mp_source=share
370
+ [👨🏼‍🏫expsup-upwork-img]: https://img.shields.io/badge/UpWork-13544E?style=for-the-badge&logo=Upwork&logoColor=white
371
+ [👨🏼‍🏫expsup-codementor]: https://www.codementor.io/peterboling?utm_source=github&utm_medium=button&utm_term=peterboling&utm_campaign=github
372
+ [👨🏼‍🏫expsup-codementor-img]: https://img.shields.io/badge/CodeMentor-Get_Help-1abc9c?style=for-the-badge&logo=CodeMentor&logoColor=white
373
+ [🏙️entsup-tidelift]: https://tidelift.com/subscription/pkg/rubygems-sanitize_email?utm_source=rubygems-sanitize_email&utm_medium=referral&utm_campaign=readme
374
+ [🏙️entsup-tidelift-img]: https://img.shields.io/badge/Tidelift_and_Sonar-Enterprise_Support-FD3456?style=for-the-badge&logo=sonar&logoColor=white
375
+ [🏙️entsup-tidelift-sonar]: https://blog.tidelift.com/tidelift-joins-sonar
376
+ [💁🏼‍♂️peterboling]: http://www.peterboling.com
377
+ [🚂railsbling]: http://www.railsbling.com
378
+ [📜src-gl-img]: https://img.shields.io/badge/GitLab-FBA326?style=for-the-badge&logo=Gitlab&logoColor=orange
379
+ [📜src-gl]: https://gitlab.com/galtzo-floss/sanitize_email/-/tree/main/gems/sanitize_email
380
+ [📜src-cb-img]: https://img.shields.io/badge/CodeBerg-4893CC?style=for-the-badge&logo=CodeBerg&logoColor=blue
381
+ [📜src-cb]: https://codeberg.org/galtzo-floss/sanitize_email/src/branch/main/gems/sanitize_email
382
+ [📜src-gh-img]: https://img.shields.io/badge/GitHub-238636?style=for-the-badge&logo=Github&logoColor=green
383
+ [📜src-gh]: https://github.com/galtzo-floss/sanitize_email/tree/main/gems/sanitize_email
384
+ [📜docs-cr-rd-img]: https://img.shields.io/badge/RubyDoc-Current_Release-943CD2?style=for-the-badge&logo=readthedocs&logoColor=white
385
+ [📜docs-head-rd-img]: https://img.shields.io/badge/YARD_on_Galtzo.com-HEAD-943CD2?style=for-the-badge&logo=readthedocs&logoColor=white
386
+ [📜gl-wiki]: https://gitlab.com/galtzo-floss/sanitize_email/-/wikis/home
387
+ [📜gh-wiki]: https://github.com/galtzo-floss/sanitize_email/wiki
388
+ [📜gl-wiki-img]: https://img.shields.io/badge/wiki-gitlab-943CD2.svg?style=for-the-badge&logo=gitlab&logoColor=white
389
+ [📜gh-wiki-img]: https://img.shields.io/badge/wiki-github-943CD2.svg?style=for-the-badge&logo=github&logoColor=white
390
+ [👽dl-rank]: https://bestgems.org/gems/sanitize_email
391
+ [👽dl-ranki]: https://img.shields.io/gem/rd/sanitize_email.svg
392
+ [👽version]: https://bestgems.org/gems/sanitize_email
393
+ [👽versioni]: https://img.shields.io/gem/v/sanitize_email.svg
394
+ [🏀qlty-mnt]: https://qlty.sh/gh/galtzo-floss/projects/sanitize_email
395
+ [🏀qlty-mnti]: https://qlty.sh/gh/galtzo-floss/projects/sanitize_email/maintainability.svg
396
+ [🏀qlty-cov]: https://qlty.sh/gh/galtzo-floss/projects/sanitize_email/metrics/code?sort=coverageRating
397
+ [🏀qlty-covi]: https://qlty.sh/gh/galtzo-floss/projects/sanitize_email/coverage.svg
398
+ [🏀codecov]: https://codecov.io/gh/galtzo-floss/sanitize_email
399
+ [🏀codecovi]: https://codecov.io/gh/galtzo-floss/sanitize_email/graph/badge.svg
400
+ [🏀coveralls]: https://coveralls.io/github/galtzo-floss/sanitize_email?branch=main
401
+ [🏀coveralls-img]: https://coveralls.io/repos/github/galtzo-floss/sanitize_email/badge.svg?branch=main
402
+ [🚎ruby-2.4-wf]: https://github.com/galtzo-floss/sanitize_email/actions/workflows/ruby-2.4.yml
403
+ [🚎ruby-2.5-wf]: https://github.com/galtzo-floss/sanitize_email/actions/workflows/ruby-2.5.yml
404
+ [🚎ruby-2.6-wf]: https://github.com/galtzo-floss/sanitize_email/actions/workflows/ruby-2.6.yml
405
+ [🚎ruby-2.7-wf]: https://github.com/galtzo-floss/sanitize_email/actions/workflows/ruby-2.7.yml
406
+ [🚎ruby-3.0-wf]: https://github.com/galtzo-floss/sanitize_email/actions/workflows/ruby-3.0.yml
407
+ [🚎ruby-3.1-wf]: https://github.com/galtzo-floss/sanitize_email/actions/workflows/ruby-3.1.yml
408
+ [🚎ruby-3.2-wf]: https://github.com/galtzo-floss/sanitize_email/actions/workflows/ruby-3.2.yml
409
+ [🚎ruby-3.3-wf]: https://github.com/galtzo-floss/sanitize_email/actions/workflows/ruby-3.3.yml
410
+ [🚎ruby-3.4-wf]: https://github.com/galtzo-floss/sanitize_email/actions/workflows/ruby-3.4.yml
411
+ [🚎jruby-9.2-wf]: https://github.com/galtzo-floss/sanitize_email/actions/workflows/jruby-9.2.yml
412
+ [🚎jruby-9.3-wf]: https://github.com/galtzo-floss/sanitize_email/actions/workflows/jruby-9.3.yml
413
+ [🚎jruby-9.4-wf]: https://github.com/galtzo-floss/sanitize_email/actions/workflows/jruby-9.4.yml
414
+ [🚎truby-22.3-wf]: https://github.com/galtzo-floss/sanitize_email/actions/workflows/truffleruby-22.3.yml
415
+ [🚎truby-23.0-wf]: https://github.com/galtzo-floss/sanitize_email/actions/workflows/truffleruby-23.0.yml
416
+ [🚎truby-23.1-wf]: https://github.com/galtzo-floss/sanitize_email/actions/workflows/truffleruby-23.1.yml
417
+ [🚎truby-24.2-wf]: https://github.com/galtzo-floss/sanitize_email/actions/workflows/truffleruby-24.2.yml
418
+ [🚎truby-25.0-wf]: https://github.com/galtzo-floss/sanitize_email/actions/workflows/truffleruby-25.0.yml
419
+ [🚎2-cov-wf]: https://github.com/galtzo-floss/sanitize_email/actions/workflows/coverage.yml
420
+ [🚎2-cov-wfi]: https://github.com/galtzo-floss/sanitize_email/actions/workflows/coverage.yml/badge.svg
421
+ [🚎3-hd-wf]: https://github.com/galtzo-floss/sanitize_email/actions/workflows/heads.yml
422
+ [🚎3-hd-wfi]: https://github.com/galtzo-floss/sanitize_email/actions/workflows/heads.yml/badge.svg
423
+ [🚎5-st-wf]: https://github.com/galtzo-floss/sanitize_email/actions/workflows/style.yml
424
+ [🚎5-st-wfi]: https://github.com/galtzo-floss/sanitize_email/actions/workflows/style.yml/badge.svg
425
+ [🚎9-t-wf]: https://github.com/galtzo-floss/sanitize_email/actions/workflows/truffle.yml
426
+ [🚎9-t-wfi]: https://github.com/galtzo-floss/sanitize_email/actions/workflows/truffle.yml/badge.svg
427
+ [🚎10-j-wf]: https://github.com/galtzo-floss/sanitize_email/actions/workflows/jruby.yml
428
+ [🚎10-j-wfi]: https://github.com/galtzo-floss/sanitize_email/actions/workflows/jruby.yml/badge.svg
429
+ [🚎11-c-wf]: https://github.com/galtzo-floss/sanitize_email/actions/workflows/current.yml
430
+ [🚎11-c-wfi]: https://github.com/galtzo-floss/sanitize_email/actions/workflows/current.yml/badge.svg
431
+ [🚎12-crh-wf]: https://github.com/galtzo-floss/sanitize_email/actions/workflows/dep-heads.yml
432
+ [🚎12-crh-wfi]: https://github.com/galtzo-floss/sanitize_email/actions/workflows/dep-heads.yml/badge.svg
433
+ [🚎13-🔒️-wf]: https://github.com/galtzo-floss/sanitize_email/actions/workflows/locked_deps.yml
434
+ [🚎13-🔒️-wfi]: https://github.com/galtzo-floss/sanitize_email/actions/workflows/locked_deps.yml/badge.svg
435
+ [🚎14-🔓️-wf]: https://github.com/galtzo-floss/sanitize_email/actions/workflows/unlocked_deps.yml
436
+ [🚎14-🔓️-wfi]: https://github.com/galtzo-floss/sanitize_email/actions/workflows/unlocked_deps.yml/badge.svg
437
+ [🚎15-🪪-wf]: https://github.com/galtzo-floss/sanitize_email/actions/workflows/license-eye.yml
438
+ [🚎15-🪪-wfi]: https://github.com/galtzo-floss/sanitize_email/actions/workflows/license-eye.yml/badge.svg
439
+ [💎ruby-2.4i]: https://img.shields.io/badge/Ruby-2.4-DF00CA?style=for-the-badge&logo=ruby&logoColor=white
440
+ [💎ruby-2.5i]: https://img.shields.io/badge/Ruby-2.5-DF00CA?style=for-the-badge&logo=ruby&logoColor=white
441
+ [💎ruby-2.6i]: https://img.shields.io/badge/Ruby-2.6-DF00CA?style=for-the-badge&logo=ruby&logoColor=white
442
+ [💎ruby-2.7i]: https://img.shields.io/badge/Ruby-2.7-DF00CA?style=for-the-badge&logo=ruby&logoColor=white
443
+ [💎ruby-3.0i]: https://img.shields.io/badge/Ruby-3.0-CC342D?style=for-the-badge&logo=ruby&logoColor=white
444
+ [💎ruby-3.1i]: https://img.shields.io/badge/Ruby-3.1-CC342D?style=for-the-badge&logo=ruby&logoColor=white
445
+ [💎ruby-3.2i]: https://img.shields.io/badge/Ruby-3.2-CC342D?style=for-the-badge&logo=ruby&logoColor=white
446
+ [💎ruby-3.3i]: https://img.shields.io/badge/Ruby-3.3-CC342D?style=for-the-badge&logo=ruby&logoColor=white
447
+ [💎ruby-3.4i]: https://img.shields.io/badge/Ruby-3.4-CC342D?style=for-the-badge&logo=ruby&logoColor=white
448
+ [💎ruby-4.0i]: https://img.shields.io/badge/Ruby-4.0-CC342D?style=for-the-badge&logo=ruby&logoColor=white
449
+ [💎ruby-c-i]: https://img.shields.io/badge/Ruby-current-CC342D?style=for-the-badge&logo=ruby&logoColor=green
450
+ [💎ruby-headi]: https://img.shields.io/badge/Ruby-HEAD-CC342D?style=for-the-badge&logo=ruby&logoColor=blue
451
+ [💎truby-22.3i]: https://img.shields.io/badge/Truffle_Ruby-22.3-34BCB1?style=for-the-badge&logo=ruby&logoColor=pink
452
+ [💎truby-23.0i]: https://img.shields.io/badge/Truffle_Ruby-23.0-34BCB1?style=for-the-badge&logo=ruby&logoColor=pink
453
+ [💎truby-23.1i]: https://img.shields.io/badge/Truffle_Ruby-23.1-34BCB1?style=for-the-badge&logo=ruby&logoColor=pink
454
+ [💎truby-24.2i]: https://img.shields.io/badge/Truffle_Ruby-24.2-34BCB1?style=for-the-badge&logo=ruby&logoColor=pink
455
+ [💎truby-25.0i]: https://img.shields.io/badge/Truffle_Ruby-25.0-34BCB1?style=for-the-badge&logo=ruby&logoColor=pink
456
+ [💎truby-c-i]: https://img.shields.io/badge/Truffle_Ruby-current-34BCB1?style=for-the-badge&logo=ruby&logoColor=green
457
+ [💎jruby-9.2i]: https://img.shields.io/badge/JRuby-9.2-FBE742?style=for-the-badge&logo=ruby&logoColor=red
458
+ [💎jruby-9.3i]: https://img.shields.io/badge/JRuby-9.3-FBE742?style=for-the-badge&logo=ruby&logoColor=red
459
+ [💎jruby-9.4i]: https://img.shields.io/badge/JRuby-9.4-FBE742?style=for-the-badge&logo=ruby&logoColor=red
460
+ [💎jruby-c-i]: https://img.shields.io/badge/JRuby-current-FBE742?style=for-the-badge&logo=ruby&logoColor=green
461
+ [💎jruby-headi]: https://img.shields.io/badge/JRuby-HEAD-FBE742?style=for-the-badge&logo=ruby&logoColor=blue
462
+ [🤝gh-issues]: https://github.com/galtzo-floss/sanitize_email/issues
463
+ [🤝gh-pulls]: https://github.com/galtzo-floss/sanitize_email/pulls
464
+ [🤝gl-issues]: https://gitlab.com/galtzo-floss/sanitize_email/-/issues
465
+ [🤝gl-pulls]: https://gitlab.com/galtzo-floss/sanitize_email/-/merge_requests
466
+ [🤝cb-issues]: https://codeberg.org/galtzo-floss/sanitize_email/issues
467
+ [🤝cb-pulls]: https://codeberg.org/galtzo-floss/sanitize_email/pulls
468
+ [🤝cb-donate]: https://donate.codeberg.org/
469
+ [🤝contributing]: https://github.com/galtzo-floss/sanitize_email/blob/main/CONTRIBUTING.md
470
+ [🏀codecov-g]: https://codecov.io/gh/galtzo-floss/sanitize_email/graph/badge.svg
471
+ [🖐contrib-rocks]: https://contrib.rocks
472
+ [🖐contributors]: https://github.com/galtzo-floss/sanitize_email/graphs/contributors
473
+ [🖐contributors-img]: https://contrib.rocks/image?repo=galtzo-floss/sanitize_email
474
+ [🚎contributors-gl]: https://gitlab.com/galtzo-floss/sanitize_email/-/graphs/main
475
+ [🪇conduct]: https://github.com/galtzo-floss/sanitize_email/blob/main/CODE_OF_CONDUCT.md
476
+ [🪇conduct-img]: https://img.shields.io/badge/Contributor_Covenant-2.1-259D6C.svg
477
+ [📌pvc]: http://guides.rubygems.org/patterns/#pessimistic-version-constraint
478
+ [📌semver]: https://semver.org/spec/v2.0.0.html
479
+ [📌semver-img]: https://img.shields.io/badge/semver-2.0.0-259D6C.svg?style=flat
480
+ [📌semver-breaking]: https://github.com/semver/semver/issues/716#issuecomment-869336139
481
+ [📌major-versions-not-sacred]: https://tom.preston-werner.com/2022/05/23/major-version-numbers-are-not-sacred.html
482
+ [📌changelog]: https://github.com/galtzo-floss/sanitize_email/blob/main/CHANGELOG.md
483
+ [📗keep-changelog]: https://keepachangelog.com/en/1.0.0/
484
+ [📗keep-changelog-img]: https://img.shields.io/badge/keep--a--changelog-1.0.0-34495e.svg?style=flat
485
+ [📌gitmoji]: https://gitmoji.dev
486
+ [📌gitmoji-img]: https://img.shields.io/badge/gitmoji_commits-%20%F0%9F%98%9C%20%F0%9F%98%8D-34495e.svg?style=flat-square
487
+ [🧮kloc]: https://www.youtube.com/watch?v=dQw4w9WgXcQ
488
+ [🧮kloc-img]: https://img.shields.io/badge/KLOC-0.276-FFDD67.svg?style=for-the-badge&logo=YouTube&logoColor=blue
489
+ [🔐security]: https://github.com/galtzo-floss/sanitize_email/blob/main/SECURITY.md
490
+ [🔐security-img]: https://img.shields.io/badge/security-policy-259D6C.svg?style=flat
491
+ [📄copyright-notice-explainer]: https://opensource.stackexchange.com/questions/5778/why-do-licenses-such-as-the-mit-license-specify-a-single-year
492
+ [📄license]: LICENSE.md
493
+ [📄license-ref]: MIT.md
494
+ [📄license-img]: https://img.shields.io/badge/License-MIT-259D6C.svg
495
+ [📄license-compat]: https://www.apache.org/legal/resolved.html#category-a
496
+ [📄license-compat-img]: https://img.shields.io/badge/Apache_Compatible:_Category_A-✓-259D6C.svg?style=flat&logo=Apache
497
+
498
+ [📄ilo-declaration]: https://www.ilo.org/declaration/lang--en/index.htm
499
+ [📄ilo-declaration-img]: https://img.shields.io/badge/ILO_Fundamental_Principles-✓-259D6C.svg?style=flat
500
+ [🚎yard-current]: http://rubydoc.info/gems/sanitize_email
501
+ [🚎yard-head]: https://sanitize-email.galtzo.com
502
+ [💎stone_checksums]: https://github.com/galtzo-floss/stone_checksums
503
+ [💎SHA_checksums]: https://gitlab.com/galtzo-floss/sanitize_email/-/tree/main/checksums
504
+ [💎rlts]: https://github.com/rubocop-lts/rubocop-lts
505
+ [💎rlts-img]: https://img.shields.io/badge/code_style_&_linting-rubocop--lts-34495e.svg?plastic&logo=ruby&logoColor=white
506
+ [💎appraisal2]: https://github.com/appraisal-rb/appraisal2
507
+ [💎appraisal2-img]: https://img.shields.io/badge/appraised_by-appraisal2-34495e.svg?plastic&logo=ruby&logoColor=white
508
+ [💎d-in-dvcs]: https://railsbling.com/posts/dvcs/put_the_d_in_dvcs/
509
+
510
+ <!-- kettle-jem:metadata:start -->
511
+ | Field | Value |
512
+ |---|---|
513
+ | Package | sanitize_email |
514
+ | Description | Email Condom for your Ruby Server.<br>In Rails, Sinatra, et al, or simply the mail gem: Aids in development, testing, qa, and production troubleshooting of email issues without worrying that emails will get sent to actual live addresses. |
515
+ | Homepage | https://github.com/galtzo-floss/sanitize_email |
516
+ | Source | https://github.com/galtzo-floss/sanitize_email/tree/v2.0.10 |
517
+ | License | `MIT` |
518
+ | Funding | https://github.com/sponsors/pboling, https://issuehunt.io/u/pboling, https://ko-fi.com/pboling, https://liberapay.com/pboling/donate, https://patreon.com/galtzo, https://polar.sh/pboling, https://thanks.dev/gh/pboling, https://tidelift.com/funding/github/rubygems/sanitize_email, https://www.buymeacoffee.com/pboling |
519
+ <!-- kettle-jem:metadata:end -->