sanitize_email 2.0.10 → 2.0.12

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,25 @@
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
+ <a href="https://github.com/galtzo-floss"><img alt="galtzo-floss Logo by Aboling0, CC BY-SA 4.0" src="https://logos.galtzo.com/assets/images/galtzo-floss/avatar-128px.svg" width="12%" align="right"/></a> <a href="https://github.com/galtzo-floss/sanitize_email"><img alt="sanitize_email Logo by Aboling0, CC BY-SA 4.0" src="https://logos.galtzo.com/assets/images/galtzo-floss/sanitize_email/avatar-128px.svg" width="12%" align="right"/></a>
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
+ # 📧 SanitizeEmail
66
4
 
67
- In addition, this gem solves problems that `mailcatcher` does not solve. I recommend using both!
5
+ [![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]
68
6
 
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.
7
+ `if ci_badges.map(&:color).detect { it != "green"}` ☝️ [let me know][✉️discord-invite], as I may have missed the [discord notification][✉️discord-invite].
72
8
 
73
- It is a bit like using the "test" Visa credit card number `4701322211111234` with a real payment gateway.
9
+ ---
74
10
 
75
- ## Encryption
11
+ `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.
76
12
 
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.
13
+ [![OpenCollective Backers][🖇osc-backers-i]][🖇osc-backers] [![OpenCollective Sponsors][🖇osc-sponsors-i]][🖇osc-sponsors] [![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]
80
14
 
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.
15
+ <details>
16
+ <summary>👣 How will this project approach the September 2025 hostile takeover of RubyGems? 🚑️</summary>
83
17
 
84
- ## Compatibility
18
+ I've summarized my thoughts in [this blog post](https://dev.to/galtzo/hostile-takeover-of-rubygems-my-thoughts-5hlo).
85
19
 
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!
20
+ </details>
92
21
 
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/
109
-
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
22
+ ## 🌻 Synopsis <a href="https://discord.gg/3qme4XHNKN"><img alt="Galtzo FLOSS Logo by Aboling0, CC BY-SA 4.0" src="https://logos.galtzo.com/assets/images/galtzo-floss/avatar-128px.svg" width="8%" align="right"/></a> <a href="https://ruby-toolbox.com"><img alt="ruby-lang Logo, Yukihiro Matsumoto, Ruby Visual Identity Team, CC BY-SA 2.5" src="https://logos.galtzo.com/assets/images/ruby-lang/avatar-128px.svg" width="8%" align="right"/></a>
225
23
 
226
24
  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
25
 
@@ -234,157 +32,89 @@ It's particularly helpful when you want to prevent the delivery of email (e.g. i
234
32
  * solves common problems in ruby web applications that use email
235
33
  * provides test helpers and spec matchers to assist with testing email content delivery
236
34
 
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:
35
+ ## 💡 Info you can shake a stick at
269
36
 
270
- gem 'sanitize_email'
37
+ | Tokens to Remember | [![Gem name][⛳️name-img]][⛳️gem-name] [![Gem namespace][⛳️namespace-img]][⛳️gem-namespace] |
38
+ |-------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
39
+ | 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]|
40
+ | 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]|
41
+ | 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]|
42
+ | 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]|
43
+ | Works with MRI Ruby 2 | ![Ruby 2.3 Compat][💎ruby-2.3i] <br/> [![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]|
44
+ | 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] |
45
+ | 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] |
46
+ | 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] |
47
+ | 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] |
48
+ | 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] |
49
+ | 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] |
50
+ | `...` 💖 | [![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] |
271
51
 
272
- Then:
52
+ ### Compatibility
273
53
 
274
- bundle install
54
+ Compatible with MRI Ruby 2.3.0+, and concordant releases of JRuby, and TruffleRuby.
55
+ CI workflows and Appraisals are generated for MRI Ruby 2.4+.
56
+ This test floor is configured by `ruby.test_minimum` in `.kettle-jem.yml` and
57
+ may be higher than the gem's runtime compatibility floor when legacy Rubies are
58
+ not practical for the current toolchain.
275
59
 
276
- ## Setup with Ruby
60
+ | 🚚 _Amazing_ test matrix was brought to you by | 🔎 appraisal2 🔎 and the color 💚 green 💚 |
61
+ |------------------------------------------------|--------------------------------------------------------|
62
+ | 👟 Check it out! | ✨ [github.com/appraisal-rb/appraisal2][💎appraisal2] ✨ |
277
63
 
278
- _keep scrolling for Rails, but read this for a better understanding of Magic_
64
+ ### Federated DVCS
279
65
 
280
- There are three ways SanitizeEmail can be turned on; in order of precedence they are:
66
+ <details markdown="1">
67
+ <summary>Find this repo on federated forges (Coming soon!)</summary>
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.
69
+ | Federated [DVCS][💎d-in-dvcs] Repository | Status | Issues | PRs | Wiki | CI | Discussions |
70
+ |-------------------------------------------------|-----------------------------------------------------------------------|---------------------------|--------------------------|---------------------------|--------------------------|------------------------------|
71
+ | 🧪 [galtzo-floss/sanitize_email on GitLab][📜src-gl] | The Truth | [💚][🤝gl-issues] | [💚][🤝gl-pulls] | [💚][📜gl-wiki] | 🐭 Tiny Matrix | ➖ |
72
+ | 🧊 [galtzo-floss/sanitize_email on CodeBerg][📜src-cb] | An Ethical Mirror ([Donate][🤝cb-donate]) | [💚][🤝cb-issues] | [💚][🤝cb-pulls] | ➖ | ⭕️ No Matrix | ➖ |
73
+ | 🐙 [galtzo-floss/sanitize_email on GitHub][📜src-gh] | Another Mirror | [💚][🤝gh-issues] | [💚][🤝gh-pulls] | [💚][📜gh-wiki] | 💯 Full Matrix | [💚][gh-discussions] |
74
+ | 🎮️ [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] |
283
75
 
284
- SanitizeEmail.force_sanitize = true # by default it is nil
76
+ </details>
285
77
 
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:
78
+ [gh-discussions]: https://github.com/galtzo-floss/sanitize_email/discussions
287
79
 
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)
80
+ ### 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)
290
81
 
291
- Once registered, SanitizeEmail needs to be engaged:
82
+ Available as part of the Tidelift Subscription.
292
83
 
293
- # in config/initializers/sanitize_email.rb
294
- SanitizeEmail::Config.configure { |config| config[:engage] = true }
84
+ <details markdown="1">
85
+ <summary>Need enterprise-level guarantees?</summary>
295
86
 
296
- 3. If you don't need to compute anything, then don't use this option, go with the previous option.
87
+ 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.
297
88
 
298
- SanitizeEmail::Config.configure { |config| config[:activation_proc] = proc { true } } # by default :activation_proc is false
89
+ [![Get help from me on Tidelift][🏙️entsup-tidelift-img]][🏙️entsup-tidelift]
299
90
 
300
- ### Examples
91
+ - 💡Subscribe for support guarantees covering _all_ your FLOSS dependencies
92
+ - 💡Tidelift is part of [Sonar][🏙️entsup-tidelift-sonar]
93
+ - 💡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
301
94
 
302
- #### Only allow email to a specific domain
95
+ Alternatively:
303
96
 
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.
97
+ - [![Live Chat on Discord][✉️discord-invite-img-ftb]][✉️discord-invite]
98
+ - [![Get help from me on Upwork][👨🏼‍🏫expsup-upwork-img]][👨🏼‍🏫expsup-upwork]
99
+ - [![Get help from me on Codementor][👨🏼‍🏫expsup-codementor-img]][👨🏼‍🏫expsup-codementor]
306
100
 
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
101
+ </details>
315
102
 
316
- ### Notes
103
+ ## ✨ Installation
317
104
 
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.
105
+ Install the gem and add to the application's Gemfile by executing:
320
106
 
321
- ### Troubleshooting
107
+ ```console
108
+ bundle add sanitize_email
109
+ ```
322
110
 
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:
111
+ If bundler is not being used to manage dependencies, install the gem by executing:
324
112
 
325
- # in config/initializers/sanitize_email.rb
326
- Mail.register_interceptor(SanitizeEmail::Bleach)
327
- SanitizeEmail::Config.configure { |config| config[:engage] = true }
113
+ ```console
114
+ gem install sanitize_email
115
+ ```
328
116
 
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.
331
-
332
- ## Setup With Rails
333
-
334
- Create an initializer, if you are using rails, or otherwise configure:
335
-
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
346
-
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
- SanitizeEmail.sanitary(sanitized_to: "boo@example.com") do # these config options are merged with the globals
379
- Mail.deliver do
380
- from "from@example.org"
381
- to "to@example.org" # Will actually be sent to the override addresses, in this case: boo@example.com
382
- reply_to "reply_to@example.org"
383
- subject "subject"
384
- end
385
- end
386
-
387
- ## Configuration Options
117
+ ## ⚙️ Configuration
388
118
 
389
119
  As used in the "Description" column below, `engaged` means: `SanitizeEmail.activate?(message) # => true`.
390
120
  This happens in a few different ways, and two of them are in the config below (`engage` and `activation_proc`).
@@ -403,337 +133,415 @@ This happens in a few different ways, and two of them are in the config below (`
403
133
  | engage | [Boolean, nil] | Boolean will turn engage or disengage this gem, while `nil` ignores this setting and instead checks `activation_proc` |
404
134
  | activation_proc | [Proc, Lambda, #call] | When checked, due to `engage: nil`, the result will either engage or disengage this gem |
405
135
 
406
- ## Thread Safety
407
-
408
- So long as you don't change the config after initializing it at runtime, you'll be fine.
409
- Like many Ruby tools' config objects, it is a single config object, shared by all threads.
410
- The helpers like `sanitary`, `unsanitary`, `janitor`, and `force_sanitize`
411
- are intended to be used in single threaded environments,
412
- like a test suite, or a console session.
413
-
414
- I doubt I'll ever have a need for runtime reconfiguration of the config,
415
- so I doubt I'll ever have a reason to make it "more" thread safe than it is now, but PRs are welcome!
416
-
417
- ## Use sanitize_email in your test suite!
418
-
419
- ### rspec
420
-
421
- In your `spec_helper.rb`:
422
-
423
-
424
- require "sanitize_email"
425
- # rspec matchers are *not* loaded by default in sanitize_email, as it is not primarily a gem for test suites.
426
- require "sanitize_email/rspec_matchers"
427
-
428
- SanitizeEmail::Config.configure do |config|
429
- config[:sanitized_to] = "sanitize_email@example.org"
430
- config[:sanitized_cc] = "sanitize_email@example.org"
431
- config[:sanitized_bcc] = "sanitize_email@example.org"
432
- # run/call whatever logic should turn sanitize_email on and off in this Proc.
433
- # config[:activation_proc] = Proc.new { true }
434
- # 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.
435
- # Thus instead of using the Proc (slower) we just engage it always:
436
- config[:engage] = true
437
- config[:use_actual_email_prepended_to_subject] = true # or false
438
- config[:use_actual_environment_prepended_to_subject] = true # or false
439
- config[:use_actual_email_as_sanitized_user_name] = true # or false
440
- end
441
-
442
- # If your mail system is not one that sanitize_email automatically configures an interceptor for (ActionMailer, Mail)
443
- # then you will need to do the equivalent for whatever Mail system you are using.
444
-
445
- RSpec.configure do |config|
446
- # ...
447
- # From sanitize_email gem
448
- config.include(SanitizeEmail::RspecMatchers)
449
- end
450
-
451
- context "an email test" do
452
- subject { Mail.deliver(@message_hash) }
453
- it { should have_to("sanitize_email@example.org") }
454
- end
455
-
456
- #### have_* matchers
136
+ ## 🔧 Basic Usage
457
137
 
458
- These will look for an email address in any of the following mail attributes:
138
+ ## 🦷 FLOSS Funding
459
139
 
460
- [:from, :to, :cc, :bcc, :subject, :reply_to]
140
+ While galtzo-floss tools are free software and will always be, the project would benefit immensely from some funding.
141
+ Raising a monthly budget of... "dollars" would make the project more sustainable.
461
142
 
462
- Example:
143
+ We welcome both individual and corporate sponsors! We also offer a
144
+ wide array of funding channels to account for your preferences.
145
+ Currently, [Open Collective][🖇osc] is our preferred funding platform.
463
146
 
464
- context "the subject line must have the email address sanitize_email@example.org" do
465
- subject { Mail.deliver(@message_hash) }
466
- it { should have_subject("sanitize_email@example.org") }
467
- end
147
+ **If you're working in a company that's making significant use of galtzo-floss tools we'd
148
+ appreciate it if you suggest to your company to become a galtzo-floss sponsor.**
468
149
 
469
- #### be_* matchers
150
+ You can support the development of galtzo-floss tools via
151
+ [GitHub Sponsors][🖇sponsor],
152
+ [Liberapay][⛳liberapay],
153
+ [PayPal][🖇paypal],
154
+ [Open Collective][🖇osc]
155
+ and [Tidelift][🏙️entsup-tidelift].
470
156
 
471
- These will look for a matching string in any of the following attributes:
157
+ | 📍 NOTE |
158
+ |----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
159
+ | 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. |
472
160
 
473
- [:from, :to, :cc, :bcc, :subject, :reply_to]
161
+ ### Open Collective for Individuals
474
162
 
475
- Example:
163
+ Support us with a monthly donation and help us continue our activities. [[Become a backer](https://opencollective.com/galtzo-floss#backer)]
476
164
 
477
- context "the subject line must have the string 'foobarbaz'" do
478
- subject { Mail.deliver(@message_hash) }
479
- it { should be_subject("foobarbaz") }
480
- end
165
+ NOTE: [kettle-readme-backers][kettle-readme-backers] updates this list every day, automatically.
481
166
 
482
- #### have_to_username matcher
167
+ <!-- OPENCOLLECTIVE-INDIVIDUALS:START -->
168
+ No backers yet. Be the first!
169
+ <!-- OPENCOLLECTIVE-INDIVIDUALS:END -->
483
170
 
484
- The `username` in the `:to` field is when the `:to` field is formatted like this:
171
+ ### Open Collective for Organizations
485
172
 
486
- `"Peter Boling" <sanitize_email@example.org>`
173
+ Become a sponsor and get your logo on our README on GitHub with a link to your site. [[Become a sponsor](https://opencollective.com/galtzo-floss#sponsor)]
487
174
 
488
- Example:
175
+ NOTE: [kettle-readme-backers][kettle-readme-backers] updates this list every day, automatically.
489
176
 
490
- context "the to field must have the username 'Peter Boling'" do
491
- subject { Mail.deliver(@message_hash) }
492
- it { should have_to_username("Peter Boling") }
493
- end
177
+ <!-- OPENCOLLECTIVE-ORGANIZATIONS:START -->
178
+ No sponsors yet. Be the first!
179
+ <!-- OPENCOLLECTIVE-ORGANIZATIONS:END -->
494
180
 
495
- #### have_sanitized_to_header matcher
181
+ [kettle-readme-backers]: https://github.com/galtzo-floss/sanitize_email/blob/main/exe/kettle-readme-backers
496
182
 
497
- Matches any part of the value of the first sanitized to header (`"X-Sanitize-Email-To"`),
498
- which could be formatted like this:
183
+ ### Another way to support open-source
499
184
 
500
- `"Peter Boling" <sanitize_email@example.org>`
185
+ 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).
501
186
 
502
- NOTE: It won't match subsequent headers like `"X-Sanitize-Email-To-2"`, or `"X-Sanitize-Email-To-3"`.
187
+ 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`.
503
188
 
504
- Example:
189
+ 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.
505
190
 
506
- context "the first 'X-Sanitize-Email-To' header must have the username 'Peter Boling'" do
507
- subject { Mail.deliver(@message_hash) }
508
- it { should have_sanitized_to_header("Peter Boling") }
509
- end
191
+ **[Floss-Funding.dev][🖇floss-funding.dev]: 👉️ No network calls. 👉️ No tracking. 👉️ No oversight. 👉️ Minimal crypto hashing. 💡 Easily disabled nags**
510
192
 
511
- #### have_cc_username matcher
193
+ [![OpenCollective Backers][🖇osc-backers-i]][🖇osc-backers] [![OpenCollective Sponsors][🖇osc-sponsors-i]][🖇osc-sponsors] [![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]
512
194
 
513
- The `username` in the `:cc` field is when the `:c` field is formatted like this:
195
+ ## 🔐 Security
514
196
 
515
- `"Peter Boling" <sanitize_email@example.org>`
197
+ See [SECURITY.md][🔐security].
516
198
 
517
- Example:
518
-
519
- context "the cc field must have the username 'Peter Boling'" do
520
- subject { Mail.deliver(@message_hash) }
521
- it { should have_cc_username("Peter Boling") }
522
- end
523
-
524
- #### have_sanitized_cc_header matcher
525
-
526
- Matches any part of the value of the first sanitized cc header (`"X-Sanitize-Email-Cc"`),
527
- which could be formatted like this:
528
-
529
- `"Peter Boling" <sanitize_email@example.org>`
530
-
531
- NOTE: It won't match subsequent headers like `"X-Sanitize-Email-Cc-2"`, or `"X-Sanitize-Email-Cc-3"`.
532
-
533
- Example:
534
-
535
- context "the first 'X-Sanitize-Email-Cc' header must have the username 'Peter Boling'" do
536
- subject { Mail.deliver(@message_hash) }
537
- it { should have_sanitized_cc_header("Peter Boling") }
538
- end
539
-
540
- ### non-rspec (Test::Unit, mini-test, etc)
541
-
542
- In your setup file:
543
-
544
- require "sanitize_email"
545
- # test helpers are *not* loaded by default in sanitize_email, as it is not primarily a gem for test suites.
546
- require "sanitize_email/test_helpers"
547
-
548
- SanitizeEmail::Config.configure do |config|
549
- config[:sanitized_to] = "sanitize_email@example.org"
550
- config[:sanitized_cc] = "sanitize_email@example.org"
551
- config[:sanitized_bcc] = "sanitize_email@example.org"
552
- # run/call whatever logic should turn sanitize_email on and off in this Proc.
553
- # config[:activation_proc] = Proc.new { true }
554
- # 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.
555
- # Thus instead of using the Proc (slower) we just engage it always:
556
- config[:engage] = true
557
- config[:use_actual_email_prepended_to_subject] = true # or false
558
- config[:use_actual_environment_prepended_to_subject] = true # or false
559
- config[:use_actual_email_as_sanitized_user_name] = true # or false
560
- end
561
-
562
- # If your mail system is not one that sanitize_email automatically configures an interceptor for (ActionMailer, Mail)
563
- # then you will need to do the equivalent for whatever Mail system you are using.
564
-
565
- # You need to know what to do here... somehow get the methods into rhw scope of your tests.
566
- # Something like this maybe?
567
- include SanitizeEmail::TestHelpers
568
- # Look here to see what it gives you:
569
- # https://github.com/pboling/sanitize_email/blob/master/lib/sanitize_email/test_helpers.rb
570
-
571
- ## Deprecations
572
-
573
- 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:
199
+ ## 🤝 Contributing
574
200
 
575
- SanitizeEmail::Deprecation.deprecate_in_silence = true
201
+ If you need some ideas of where to help, you could work on adding more code coverage,
202
+ or if it is already 💯 (see [below](#code-coverage)) check [issues][🤝gh-issues] or [PRs][🤝gh-pulls],
203
+ or use the gem and think about how it could be better.
576
204
 
577
- ## Authors
205
+ We [![Keep A Changelog][📗keep-changelog-img]][📗keep-changelog] so if you make changes, remember to update it.
578
206
 
579
- Peter Boling is the original author of the code, and current maintainer.
207
+ See [CONTRIBUTING.md][🤝contributing] for more detailed instructions.
580
208
 
581
- Thanks to John Trupiano for turning Peter's original Rails plugin into the initial cut of this gem!
209
+ ### 🚀 Release Instructions
582
210
 
583
- ## 🤝 Contributing
211
+ See [CONTRIBUTING.md][🤝contributing].
584
212
 
585
- See [CONTRIBUTING.md][🤝contributing]
213
+ ### Code Coverage
586
214
 
587
- [🤝contributing]: CONTRIBUTING.md
215
+ <details markdown="1">
216
+ <summary>Coverage service badges</summary>
588
217
 
589
- ### You can help!
218
+ [![Coverage Graph][🏀codecov-g]][🏀codecov]
590
219
 
591
- Take a look at the `reek` list which is the file called `REEK` and start fixing things.
220
+ [![Coveralls Test Coverage][🏀coveralls-img]][🏀coveralls]
592
221
 
593
- To refresh the `reek` list:
222
+ [![QLTY Test Coverage][🏀qlty-covi]][🏀qlty-cov]
594
223
 
595
- `bundle exec reek > REEK`
224
+ </details>
596
225
 
597
- Then follow these instructions:
226
+ ### 🪇 Code of Conduct
598
227
 
599
- 1. Fork the repository
600
- 2. Create your feature branch (`git checkout -b my-new-feature`)
601
- 3. Make some fixes.
602
- 4. Commit your changes (`git commit -am 'Added some feature'`)
603
- 5. Push to the branch (`git push origin my-new-feature`)
604
- 6. Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
605
- 7. Create new Pull Request.
228
+ Everyone interacting with this project's codebases, issue trackers,
229
+ chat rooms and mailing lists agrees to follow the [![Contributor Covenant 2.1][🪇conduct-img]][🪇conduct].
606
230
 
607
231
  ## 🌈 Contributors
608
232
 
609
- [![Contributors][🌈contrib-rocks-img]][🐙hub-contrib]
610
-
611
- Contributor tiles (GitHub only) made with [contributors-img][🌈contrib-rocks].
612
-
613
- Learn more about, or become one of, our 🎖 contributors on:
614
-
615
- | Any | Of | These | DVCS |
616
- |-------------------------------------|---------------------------------------|-------------------------------------|-------------------------------------|
617
- | [🐙hub contributors][🐙hub-contrib] | [🧊berg contributors][🧊berg-contrib] | [🛖hut contributors][🛖hut-contrib] | [🧪lab contributors][🧪lab-contrib] |
618
-
619
- [comment]: <> ( DVCS CONTRIB LINKS )
233
+ [![Contributors][🖐contributors-img]][🖐contributors]
620
234
 
621
- [🌈contrib-rocks]: https://contrib.rocks
622
- [🌈contrib-rocks-img]: https://contrib.rocks/image?repo=pboling/sanitize_email
235
+ Made with [contributors-img][🖐contrib-rocks].
623
236
 
624
- [🧊berg-contrib]: https://codeberg.org/pboling/sanitize_email/activity
625
- [🐙hub-contrib]: https://github.com/pboling/sanitize_email/graphs/contributors
626
- [🛖hut-contrib]: https://git.sr.ht/~galtzo/sanitize_email/log/
627
- [🧪lab-contrib]: https://gitlab.com/pboling/sanitize_email/-/graphs/main?ref_type=heads
237
+ Also see GitLab Contributors: [https://gitlab.com/galtzo-floss/sanitize_email/-/graphs/main][🚎contributors-gl]
628
238
 
629
- ## Star History
239
+ <details>
240
+ <summary>⭐️ Star History</summary>
630
241
 
631
- <a href="https://star-history.com/#pboling/sanitize_email&Date">
242
+ <a href="https://star-history.com/galtzo-floss/sanitize_email&Date">
632
243
  <picture>
633
- <source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/svg?repos=pboling/sanitize_email&type=Date&theme=dark" />
634
- <source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/svg?repos=pboling/sanitize_email&type=Date" />
635
- <img alt="Star History Chart" src="https://api.star-history.com/svg?repos=pboling/sanitize_email&type=Date" />
244
+ <source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/svg?repos=galtzo-floss/sanitize_email&type=Date&theme=dark" />
245
+ <source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/svg?repos=galtzo-floss/sanitize_email&type=Date" />
246
+ <img alt="Star History Chart" src="https://api.star-history.com/svg?repos=galtzo-floss/sanitize_email&type=Date" />
636
247
  </picture>
637
248
  </a>
638
249
 
639
- ## Running Specs
640
-
641
- The basic compatibility matrix:
642
-
643
- appraisal install
644
- appraisal rake test
645
-
646
- NOTE: `appraisal install` uses the standard Gemfile, and thus adds a bunch of gems
647
- we do not need in each of our appraisal gemfiles.
648
-
649
- Instead we can do one of:
650
-
651
- BUNDLE_GEMFILE=gemfiles/vanilla.gemfile appraisal generate
652
- BUNDLE_GEMFILE=gemfiles/vanilla.gemfile appraisal update
653
-
654
- NOTE: This results in bad paths to the gemspec from each of the appraisal `gemfiles/rails_*_*.gemfile` files.
655
- `gemspec path: "../../"` needs to be replaced with `gemspec path: "../"` in each Appraisal gemfile.
656
-
657
- It is unlikely to be possible to install all of the supported Rubies & Railsies in a single container...
658
- See the various github action workflows for more inspiration on running certain oldies.
250
+ </details>
659
251
 
660
- ### Code Coverage
661
-
662
- [![Coverage Graph][🔑codecov-g]][🖇codecov]
663
-
664
- [🔑codecov-g]: https://codecov.io/gh/pboling/sanitize_email/graphs/tree.svg?token=Joire8DbSW
252
+ ## 📌 Versioning
665
253
 
666
- ## 🪇 Code of Conduct
254
+ This library follows [![Semantic Versioning 2.0.0][📌semver-img]][📌semver] for its public API where practical.
255
+ For most applications, prefer the [Pessimistic Version Constraint][📌pvc] with two digits of precision.
667
256
 
668
- Everyone interacting in this project's codebases, issue trackers,
669
- chat rooms and mailing lists is expected to follow the [code of conduct][🪇conduct].
257
+ For example:
670
258
 
671
- [🪇conduct]: CODE_OF_CONDUCT.md
259
+ ```ruby
260
+ spec.add_dependency("sanitize_email", "~> 2.0")
261
+ ```
672
262
 
673
- ## 📌 Versioning
263
+ <details markdown="1">
264
+ <summary>📌 Is "Platform Support" part of the public API? More details inside.</summary>
674
265
 
675
- This Library adheres to [Semantic Versioning 2.0.0][📌semver].
676
- Violations of this scheme should be reported as bugs.
677
- Specifically, if a minor or patch version is released that breaks backward compatibility,
678
- a new version should be immediately released that restores compatibility.
679
- Breaking changes to the public API will only be introduced with new major versions.
266
+ Dropping support for a platform can be a breaking change for affected users.
267
+ If a release changes supported platforms, it should be called out clearly in the changelog and versioned with that impact in mind.
680
268
 
681
269
  To get a better understanding of how SemVer is intended to work over a project's lifetime,
682
270
  read this article from the creator of SemVer:
683
271
 
684
272
  - ["Major Version Numbers are Not Sacred"][📌major-versions-not-sacred]
685
273
 
686
- As a result of this policy, you can (and should) specify a dependency on these libraries using
687
- the [Pessimistic Version Constraint][📌pvc] with two digits of precision.
274
+ </details>
688
275
 
689
- For example:
276
+ See [CHANGELOG.md][📌changelog] for a list of releases.
690
277
 
691
- spec.add_dependency("sanitize_email", "~> 2.0")
278
+ ## 📄 License
692
279
 
693
- [comment]: <> ( 📌 VERSIONING LINKS )
280
+ The gem is available as open source under the terms of
281
+ the [MIT](MIT.md) [![License: MIT][📄license-img]][📄license-ref].
694
282
 
695
- [📌pvc]: http://guides.rubygems.org/patterns/#pessimistic-version-constraint
696
- [📌semver]: http://semver.org/
697
- [📌major-versions-not-sacred]: https://tom.preston-werner.com/2022/05/23/major-version-numbers-are-not-sacred.html
283
+ ### © Copyright
698
284
 
699
- ## References
285
+ See [LICENSE.md][📄license] for the official copyright notice.
700
286
 
701
- * [Source Code](http://github.com/pboling/sanitize_email)
702
- * [Gem Release Announcement](http://blog.smartlogicsolutions.com/2009/04/25/reintroducing-sanitize_email-work-with-production-email-without-fear/)
703
- * [Peter's Original Writeup](http://galtzo.blogspot.com/2008/11/sanitize-email-never-worry-about.html)
704
- * [Using sanitize_email to Preview HTML Emails Locally](http://blog.smartlogicsolutions.com/2009/04/30/using-sanitize-email-to-preview-html-emails-locally/)
287
+ <details markdown="1">
288
+ <summary>Copyright holders</summary>
705
289
 
706
- ## 📄 License
290
+ - Copyright (c) 2008 Peter Boling
291
+ - Copyright (c) 2009 John Trupiano
292
+ - Copyright (c) 2009-2010 pboling
293
+ - Copyright (c) 2009 Peter H. Boling
294
+ - Copyright (c) 2012 David Morton
295
+ - Copyright (c) 2012 Harry Lascelles
296
+ - Copyright (c) 2012-2018, 2022, 2024, 2026 Peter H. Boling
297
+ - Copyright (c) 2013 Adrien Siami
298
+ - Copyright (c) 2013 Chris Altman
299
+ - Copyright (c) 2014 Scott Rocher
300
+ - Copyright (c) 2017 Marcus Ilgner
301
+ - Copyright (c) 2018 Bernardo Galindo
302
+ - Copyright (c) 2024-2025 joeyparis
707
303
 
708
- The gem is available as open source under the terms of
709
- the [MIT License][📄license] [![License: MIT][📄license-img]][📄license-ref].
710
- See [LICENSE.txt][📄license] for the official [Copyright Notice][📄copyright-notice-explainer].
304
+ </details>
711
305
 
712
- [comment]: <> ( 📄 LEGAL LINKS )
306
+ ## 🤑 A request for help
713
307
 
714
- [📄copyright-notice-explainer]: https://opensource.stackexchange.com/questions/5778/why-do-licenses-such-as-the-mit-license-specify-a-single-year
715
- [📄license]: LICENSE.txt
716
- [📄license-ref]: https://opensource.org/licenses/MIT
717
- [📄license-img]: https://img.shields.io/badge/License-MIT-green.svg
308
+ Maintainers have teeth and need to pay their dentists.
309
+ After getting laid off in an RIF in March, and encountering difficulty finding a new one,
310
+ I began spending most of my time building open source tools.
311
+ I'm hoping to be able to pay for my kids' health insurance this month,
312
+ so if you value the work I am doing, I need your support.
313
+ Please consider sponsoring me or the project.
718
314
 
719
- ### © Copyright
315
+ To join the community or get help 👇️ Join the Discord.
720
316
 
721
- * Copyright (c) 2009 [John Trupiano](http://smartlogicsolutions.com/wiki/John_Trupiano) of [SmartLogic Solutions, LLC](http://www.smartlogicsolutions.com)
722
- * Copyright (c) 2008 - 2018, 2020, 2022, 2024 [Peter H. Boling][peterboling] of [Rails Bling][railsbling]
317
+ [![Live Chat on Discord][✉️discord-invite-img-ftb]][✉️discord-invite]
723
318
 
724
- [railsbling]: http://www.railsbling.com
725
- [peterboling]: http://www.peterboling.com
319
+ To say "thanks!" ☝️ Join the Discord or 👇️ send money.
726
320
 
727
- ## 🤑 One more thing
321
+ [![Sponsor galtzo-floss/sanitize_email on Open Source Collective][🖇osc-all-bottom-img]][🖇osc] 💌 [![Sponsor me on GitHub Sponsors][🖇sponsor-bottom-img]][🖇sponsor] 💌 [![Sponsor me on Liberapay][⛳liberapay-bottom-img]][⛳liberapay] 💌 [![Donate on PayPal][🖇paypal-bottom-img]][🖇paypal]
728
322
 
729
- You made it to the bottom of the page,
730
- so perhaps you'll indulge me for another 20 seconds.
731
- I maintain many dozens of gems, including this one,
732
- because I want Ruby to be a great place for people to solve problems, big and small.
733
- Please consider supporting my efforts via the giant yellow link below,
734
- or one of the others at the head of this README.
323
+ ### Please give the project a star ⭐ ♥.
735
324
 
736
- [![Buy me a latte][🖇buyme-img]][🖇buyme]
325
+ Many parts of this project are actively managed by a [kettle-jem](https://github.com/structuredmerge/structuredmerge-ruby/tree/main/gems/kettle-jem) smart template utilizing [StructuredMerge.org](https://structuredmerge.org) merge contracts.
737
326
 
327
+ Thanks for RTFM. ☺️
328
+
329
+ [⛳liberapay-img]: https://img.shields.io/liberapay/goal/pboling.svg?logo=liberapay&color=a51611&style=flat
330
+ [⛳liberapay-bottom-img]: https://img.shields.io/liberapay/goal/pboling.svg?style=for-the-badge&logo=liberapay&color=a51611
331
+ [⛳liberapay]: https://liberapay.com/pboling/donate
332
+ [🖇osc-all-img]: https://img.shields.io/opencollective/all/galtzo-floss
333
+ [🖇osc-sponsors-img]: https://img.shields.io/opencollective/sponsors/galtzo-floss
334
+ [🖇osc-backers-img]: https://img.shields.io/opencollective/backers/galtzo-floss
335
+ [🖇osc-backers]: https://opencollective.com/galtzo-floss#backer
336
+ [🖇osc-backers-i]: https://opencollective.com/galtzo-floss/backers/badge.svg?style=flat
337
+ [🖇osc-sponsors]: https://opencollective.com/galtzo-floss#sponsor
338
+ [🖇osc-sponsors-i]: https://opencollective.com/galtzo-floss/sponsors/badge.svg?style=flat
339
+ [🖇osc-all-bottom-img]: https://img.shields.io/opencollective/all/galtzo-floss?style=for-the-badge
340
+ [🖇osc-sponsors-bottom-img]: https://img.shields.io/opencollective/sponsors/galtzo-floss?style=for-the-badge
341
+ [🖇osc-backers-bottom-img]: https://img.shields.io/opencollective/backers/galtzo-floss?style=for-the-badge
342
+ [🖇osc]: https://opencollective.com/galtzo-floss
343
+ [🖇sponsor-img]: https://img.shields.io/badge/Sponsor_Me!-pboling.svg?style=social&logo=github
344
+ [🖇sponsor-bottom-img]: https://img.shields.io/badge/Sponsor_Me!-pboling-blue?style=for-the-badge&logo=github
345
+ [🖇sponsor]: https://github.com/sponsors/pboling
346
+ [🖇polar-img]: https://img.shields.io/badge/polar-donate-a51611.svg?style=flat
347
+ [🖇polar]: https://polar.sh/pboling
348
+ [🖇kofi-img]: https://img.shields.io/badge/ko--fi-%E2%9C%93-a51611.svg?style=flat
349
+ [🖇kofi]: https://ko-fi.com/pboling
350
+ [🖇patreon-img]: https://img.shields.io/badge/patreon-donate-a51611.svg?style=flat
351
+ [🖇patreon]: https://patreon.com/galtzo
352
+ [🖇buyme-small-img]: https://img.shields.io/badge/buy_me_a_coffee-%E2%9C%93-a51611.svg?style=flat
738
353
  [🖇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
739
354
  [🖇buyme]: https://www.buymeacoffee.com/pboling
355
+ [🖇paypal-img]: https://img.shields.io/badge/donate-paypal-a51611.svg?style=flat&logo=paypal
356
+ [🖇paypal-bottom-img]: https://img.shields.io/badge/donate-paypal-a51611.svg?style=for-the-badge&logo=paypal&color=0A0A0A
357
+ [🖇paypal]: https://www.paypal.com/paypalme/peterboling
358
+ [🖇floss-funding.dev]: https://floss-funding.dev
359
+ [🖇floss-funding-gem]: https://github.com/galtzo-floss/floss_funding
360
+ [✉️discord-invite]: https://discord.gg/3qme4XHNKN
361
+ [✉️discord-invite-img-ftb]: https://img.shields.io/discord/1373797679469170758?style=for-the-badge&logo=discord
362
+ [✉️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
363
+ [✉️ruby-friends]: https://app.daily.dev/squads/rubyfriends
364
+
365
+ [✇bundle-group-pattern]: https://gist.github.com/pboling/4564780
366
+ [⛳️gem-namespace]: https://github.com/galtzo-floss/sanitize_email
367
+ [⛳️namespace-img]: https://img.shields.io/badge/namespace-SanitizeEmail-3C2D2D.svg?style=square&logo=ruby&logoColor=white
368
+ [⛳️gem-name]: https://bestgems.org/gems/sanitize_email
369
+ [⛳️name-img]: https://img.shields.io/badge/name-sanitize__email-3C2D2D.svg?style=square&logo=rubygems&logoColor=red
370
+ [⛳️tag-img]: https://img.shields.io/github/tag/galtzo-floss/sanitize_email.svg
371
+ [⛳️tag]: https://github.com/galtzo-floss/sanitize_email/releases
372
+ [🚂maint-blog]: http://www.railsbling.com/tags/sanitize_email
373
+ [🚂maint-blog-img]: https://img.shields.io/badge/blog-railsbling-0093D0.svg?style=for-the-badge&logo=rubyonrails&logoColor=orange
374
+ [🚂maint-contact]: http://www.railsbling.com/contact
375
+ [🚂maint-contact-img]: https://img.shields.io/badge/Contact-Maintainer-0093D0.svg?style=flat&logo=rubyonrails&logoColor=red
376
+ [💖🖇linkedin]: http://www.linkedin.com/in/peterboling
377
+ [💖🖇linkedin-img]: https://img.shields.io/badge/LinkedIn-Profile-0B66C2?style=flat&logo=newjapanprowrestling
378
+ [💖✌️wellfound]: https://wellfound.com/u/peter-boling
379
+ [💖✌️wellfound-img]: https://img.shields.io/badge/peter--boling-orange?style=flat&logo=wellfound
380
+ [💖💲crunchbase]: https://www.crunchbase.com/person/peter-boling
381
+ [💖💲crunchbase-img]: https://img.shields.io/badge/peter--boling-purple?style=flat&logo=crunchbase
382
+ [💖🐘ruby-mast]: https://ruby.social/@galtzo
383
+ [💖🐘ruby-mast-img]: https://img.shields.io/mastodon/follow/109447111526622197?domain=https://ruby.social&style=flat&logo=mastodon&label=Ruby%20@galtzo
384
+ [💖🦋bluesky]: https://bsky.app/profile/galtzo.com
385
+ [💖🦋bluesky-img]: https://img.shields.io/badge/@galtzo.com-0285FF?style=flat&logo=bluesky&logoColor=white
386
+ [💖🌳linktree]: https://linktr.ee/galtzo
387
+ [💖🌳linktree-img]: https://img.shields.io/badge/galtzo-purple?style=flat&logo=linktree
388
+ [💖💁🏼‍♂️devto]: https://dev.to/galtzo
389
+ [💖💁🏼‍♂️devto-img]: https://img.shields.io/badge/dev.to-0A0A0A?style=flat&logo=devdotto&logoColor=white
390
+ [💖💁🏼‍♂️aboutme]: https://about.me/peter.boling
391
+ [💖💁🏼‍♂️aboutme-img]: https://img.shields.io/badge/about.me-0A0A0A?style=flat&logo=aboutme&logoColor=white
392
+ [💖🧊berg]: https://codeberg.org/pboling
393
+ [💖🐙hub]: https://github.org/pboling
394
+ [💖🛖hut]: https://sr.ht/~galtzo/
395
+ [💖🧪lab]: https://gitlab.com/pboling
396
+ [👨🏼‍🏫expsup-upwork]: https://www.upwork.com/freelancers/~014942e9b056abdf86?mp_source=share
397
+ [👨🏼‍🏫expsup-upwork-img]: https://img.shields.io/badge/UpWork-13544E?style=for-the-badge&logo=Upwork&logoColor=white
398
+ [👨🏼‍🏫expsup-codementor]: https://www.codementor.io/peterboling?utm_source=github&utm_medium=button&utm_term=peterboling&utm_campaign=github
399
+ [👨🏼‍🏫expsup-codementor-img]: https://img.shields.io/badge/CodeMentor-Get_Help-1abc9c?style=for-the-badge&logo=CodeMentor&logoColor=white
400
+ [🏙️entsup-tidelift]: https://tidelift.com/subscription/pkg/rubygems-sanitize_email?utm_source=rubygems-sanitize_email&utm_medium=referral&utm_campaign=readme
401
+ [🏙️entsup-tidelift-img]: https://img.shields.io/badge/Tidelift_and_Sonar-Enterprise_Support-FD3456?style=for-the-badge&logo=sonar&logoColor=white
402
+ [🏙️entsup-tidelift-sonar]: https://blog.tidelift.com/tidelift-joins-sonar
403
+ [💁🏼‍♂️peterboling]: http://www.peterboling.com
404
+ [🚂railsbling]: http://www.railsbling.com
405
+ [📜src-gl-img]: https://img.shields.io/badge/GitLab-FBA326?style=for-the-badge&logo=Gitlab&logoColor=orange
406
+ [📜src-gl]: https://gitlab.com/galtzo-floss/sanitize_email
407
+ [📜src-cb-img]: https://img.shields.io/badge/CodeBerg-4893CC?style=for-the-badge&logo=CodeBerg&logoColor=blue
408
+ [📜src-cb]: https://codeberg.org/galtzo-floss/sanitize_email
409
+ [📜src-gh-img]: https://img.shields.io/badge/GitHub-238636?style=for-the-badge&logo=Github&logoColor=green
410
+ [📜src-gh]: https://github.com/galtzo-floss/sanitize_email
411
+ [📜docs-cr-rd-img]: https://img.shields.io/badge/RubyDoc-Current_Release-943CD2?style=for-the-badge&logo=readthedocs&logoColor=white
412
+ [📜docs-head-rd-img]: https://img.shields.io/badge/YARD_on_Galtzo.com-HEAD-943CD2?style=for-the-badge&logo=readthedocs&logoColor=white
413
+ [📜gl-wiki]: https://gitlab.com/galtzo-floss/sanitize_email/-/wikis/home
414
+ [📜gh-wiki]: https://github.com/galtzo-floss/sanitize_email/wiki
415
+ [📜gl-wiki-img]: https://img.shields.io/badge/wiki-gitlab-943CD2.svg?style=for-the-badge&logo=gitlab&logoColor=white
416
+ [📜gh-wiki-img]: https://img.shields.io/badge/wiki-github-943CD2.svg?style=for-the-badge&logo=github&logoColor=white
417
+ [👽dl-rank]: https://bestgems.org/gems/sanitize_email
418
+ [👽dl-ranki]: https://img.shields.io/gem/rd/sanitize_email.svg
419
+ [👽version]: https://bestgems.org/gems/sanitize_email
420
+ [👽versioni]: https://img.shields.io/gem/v/sanitize_email.svg
421
+ [🏀qlty-mnt]: https://qlty.sh/gh/galtzo-floss/projects/sanitize_email
422
+ [🏀qlty-mnti]: https://qlty.sh/gh/galtzo-floss/projects/sanitize_email/maintainability.svg
423
+ [🏀qlty-cov]: https://qlty.sh/gh/galtzo-floss/projects/sanitize_email/metrics/code?sort=coverageRating
424
+ [🏀qlty-covi]: https://qlty.sh/gh/galtzo-floss/projects/sanitize_email/coverage.svg
425
+ [🏀codecov]: https://codecov.io/gh/galtzo-floss/sanitize_email
426
+ [🏀codecovi]: https://codecov.io/gh/galtzo-floss/sanitize_email/graph/badge.svg
427
+ [🏀coveralls]: https://coveralls.io/github/galtzo-floss/sanitize_email?branch=main
428
+ [🏀coveralls-img]: https://coveralls.io/repos/github/galtzo-floss/sanitize_email/badge.svg?branch=main
429
+ [🚎ruby-2.4-wf]: https://github.com/galtzo-floss/sanitize_email/actions/workflows/ruby-2.4.yml
430
+ [🚎ruby-2.5-wf]: https://github.com/galtzo-floss/sanitize_email/actions/workflows/ruby-2.5.yml
431
+ [🚎ruby-2.6-wf]: https://github.com/galtzo-floss/sanitize_email/actions/workflows/ruby-2.6.yml
432
+ [🚎ruby-2.7-wf]: https://github.com/galtzo-floss/sanitize_email/actions/workflows/ruby-2.7.yml
433
+ [🚎ruby-3.0-wf]: https://github.com/galtzo-floss/sanitize_email/actions/workflows/ruby-3.0.yml
434
+ [🚎ruby-3.1-wf]: https://github.com/galtzo-floss/sanitize_email/actions/workflows/ruby-3.1.yml
435
+ [🚎ruby-3.2-wf]: https://github.com/galtzo-floss/sanitize_email/actions/workflows/ruby-3.2.yml
436
+ [🚎ruby-3.3-wf]: https://github.com/galtzo-floss/sanitize_email/actions/workflows/ruby-3.3.yml
437
+ [🚎ruby-3.4-wf]: https://github.com/galtzo-floss/sanitize_email/actions/workflows/ruby-3.4.yml
438
+ [🚎jruby-9.2-wf]: https://github.com/galtzo-floss/sanitize_email/actions/workflows/jruby-9.2.yml
439
+ [🚎jruby-9.3-wf]: https://github.com/galtzo-floss/sanitize_email/actions/workflows/jruby-9.3.yml
440
+ [🚎jruby-9.4-wf]: https://github.com/galtzo-floss/sanitize_email/actions/workflows/jruby-9.4.yml
441
+ [🚎truby-22.3-wf]: https://github.com/galtzo-floss/sanitize_email/actions/workflows/truffleruby-22.3.yml
442
+ [🚎truby-23.0-wf]: https://github.com/galtzo-floss/sanitize_email/actions/workflows/truffleruby-23.0.yml
443
+ [🚎truby-23.1-wf]: https://github.com/galtzo-floss/sanitize_email/actions/workflows/truffleruby-23.1.yml
444
+ [🚎truby-24.2-wf]: https://github.com/galtzo-floss/sanitize_email/actions/workflows/truffleruby-24.2.yml
445
+ [🚎truby-25.0-wf]: https://github.com/galtzo-floss/sanitize_email/actions/workflows/truffleruby-25.0.yml
446
+ [🚎2-cov-wf]: https://github.com/galtzo-floss/sanitize_email/actions/workflows/coverage.yml
447
+ [🚎2-cov-wfi]: https://github.com/galtzo-floss/sanitize_email/actions/workflows/coverage.yml/badge.svg
448
+ [🚎3-hd-wf]: https://github.com/galtzo-floss/sanitize_email/actions/workflows/heads.yml
449
+ [🚎3-hd-wfi]: https://github.com/galtzo-floss/sanitize_email/actions/workflows/heads.yml/badge.svg
450
+ [🚎5-st-wf]: https://github.com/galtzo-floss/sanitize_email/actions/workflows/style.yml
451
+ [🚎5-st-wfi]: https://github.com/galtzo-floss/sanitize_email/actions/workflows/style.yml/badge.svg
452
+ [🚎9-t-wf]: https://github.com/galtzo-floss/sanitize_email/actions/workflows/truffle.yml
453
+ [🚎9-t-wfi]: https://github.com/galtzo-floss/sanitize_email/actions/workflows/truffle.yml/badge.svg
454
+ [🚎10-j-wf]: https://github.com/galtzo-floss/sanitize_email/actions/workflows/jruby.yml
455
+ [🚎10-j-wfi]: https://github.com/galtzo-floss/sanitize_email/actions/workflows/jruby.yml/badge.svg
456
+ [🚎11-c-wf]: https://github.com/galtzo-floss/sanitize_email/actions/workflows/current.yml
457
+ [🚎11-c-wfi]: https://github.com/galtzo-floss/sanitize_email/actions/workflows/current.yml/badge.svg
458
+ [🚎12-crh-wf]: https://github.com/galtzo-floss/sanitize_email/actions/workflows/dep-heads.yml
459
+ [🚎12-crh-wfi]: https://github.com/galtzo-floss/sanitize_email/actions/workflows/dep-heads.yml/badge.svg
460
+ [🚎13-🔒️-wf]: https://github.com/galtzo-floss/sanitize_email/actions/workflows/locked_deps.yml
461
+ [🚎13-🔒️-wfi]: https://github.com/galtzo-floss/sanitize_email/actions/workflows/locked_deps.yml/badge.svg
462
+ [🚎14-🔓️-wf]: https://github.com/galtzo-floss/sanitize_email/actions/workflows/unlocked_deps.yml
463
+ [🚎14-🔓️-wfi]: https://github.com/galtzo-floss/sanitize_email/actions/workflows/unlocked_deps.yml/badge.svg
464
+ [🚎15-🪪-wf]: https://github.com/galtzo-floss/sanitize_email/actions/workflows/license-eye.yml
465
+ [🚎15-🪪-wfi]: https://github.com/galtzo-floss/sanitize_email/actions/workflows/license-eye.yml/badge.svg
466
+ [💎ruby-2.3i]: https://img.shields.io/badge/Ruby-2.3_(%F0%9F%9A%ABCI)-AABBCC?style=for-the-badge&logo=ruby&logoColor=white
467
+ [💎ruby-2.4i]: https://img.shields.io/badge/Ruby-2.4-DF00CA?style=for-the-badge&logo=ruby&logoColor=white
468
+ [💎ruby-2.5i]: https://img.shields.io/badge/Ruby-2.5-DF00CA?style=for-the-badge&logo=ruby&logoColor=white
469
+ [💎ruby-2.6i]: https://img.shields.io/badge/Ruby-2.6-DF00CA?style=for-the-badge&logo=ruby&logoColor=white
470
+ [💎ruby-2.7i]: https://img.shields.io/badge/Ruby-2.7-DF00CA?style=for-the-badge&logo=ruby&logoColor=white
471
+ [💎ruby-3.0i]: https://img.shields.io/badge/Ruby-3.0-CC342D?style=for-the-badge&logo=ruby&logoColor=white
472
+ [💎ruby-3.1i]: https://img.shields.io/badge/Ruby-3.1-CC342D?style=for-the-badge&logo=ruby&logoColor=white
473
+ [💎ruby-3.2i]: https://img.shields.io/badge/Ruby-3.2-CC342D?style=for-the-badge&logo=ruby&logoColor=white
474
+ [💎ruby-3.3i]: https://img.shields.io/badge/Ruby-3.3-CC342D?style=for-the-badge&logo=ruby&logoColor=white
475
+ [💎ruby-3.4i]: https://img.shields.io/badge/Ruby-3.4-CC342D?style=for-the-badge&logo=ruby&logoColor=white
476
+ [💎ruby-4.0i]: https://img.shields.io/badge/Ruby-4.0-CC342D?style=for-the-badge&logo=ruby&logoColor=white
477
+ [💎ruby-c-i]: https://img.shields.io/badge/Ruby-current-CC342D?style=for-the-badge&logo=ruby&logoColor=green
478
+ [💎ruby-headi]: https://img.shields.io/badge/Ruby-HEAD-CC342D?style=for-the-badge&logo=ruby&logoColor=blue
479
+ [💎truby-22.3i]: https://img.shields.io/badge/Truffle_Ruby-22.3-34BCB1?style=for-the-badge&logo=ruby&logoColor=pink
480
+ [💎truby-23.0i]: https://img.shields.io/badge/Truffle_Ruby-23.0-34BCB1?style=for-the-badge&logo=ruby&logoColor=pink
481
+ [💎truby-23.1i]: https://img.shields.io/badge/Truffle_Ruby-23.1-34BCB1?style=for-the-badge&logo=ruby&logoColor=pink
482
+ [💎truby-24.2i]: https://img.shields.io/badge/Truffle_Ruby-24.2-34BCB1?style=for-the-badge&logo=ruby&logoColor=pink
483
+ [💎truby-25.0i]: https://img.shields.io/badge/Truffle_Ruby-25.0-34BCB1?style=for-the-badge&logo=ruby&logoColor=pink
484
+ [💎truby-c-i]: https://img.shields.io/badge/Truffle_Ruby-current-34BCB1?style=for-the-badge&logo=ruby&logoColor=green
485
+ [💎jruby-9.2i]: https://img.shields.io/badge/JRuby-9.2-FBE742?style=for-the-badge&logo=ruby&logoColor=red
486
+ [💎jruby-9.3i]: https://img.shields.io/badge/JRuby-9.3-FBE742?style=for-the-badge&logo=ruby&logoColor=red
487
+ [💎jruby-9.4i]: https://img.shields.io/badge/JRuby-9.4-FBE742?style=for-the-badge&logo=ruby&logoColor=red
488
+ [💎jruby-c-i]: https://img.shields.io/badge/JRuby-current-FBE742?style=for-the-badge&logo=ruby&logoColor=green
489
+ [💎jruby-headi]: https://img.shields.io/badge/JRuby-HEAD-FBE742?style=for-the-badge&logo=ruby&logoColor=blue
490
+ [🤝gh-issues]: https://github.com/galtzo-floss/sanitize_email/issues
491
+ [🤝gh-pulls]: https://github.com/galtzo-floss/sanitize_email/pulls
492
+ [🤝gl-issues]: https://gitlab.com/galtzo-floss/sanitize_email/-/issues
493
+ [🤝gl-pulls]: https://gitlab.com/galtzo-floss/sanitize_email/-/merge_requests
494
+ [🤝cb-issues]: https://codeberg.org/galtzo-floss/sanitize_email/issues
495
+ [🤝cb-pulls]: https://codeberg.org/galtzo-floss/sanitize_email/pulls
496
+ [🤝cb-donate]: https://donate.codeberg.org/
497
+ [🤝contributing]: https://github.com/galtzo-floss/sanitize_email/blob/main/CONTRIBUTING.md
498
+ [🏀codecov-g]: https://codecov.io/gh/galtzo-floss/sanitize_email/graph/badge.svg
499
+ [🖐contrib-rocks]: https://contrib.rocks
500
+ [🖐contributors]: https://github.com/galtzo-floss/sanitize_email/graphs/contributors
501
+ [🖐contributors-img]: https://contrib.rocks/image?repo=galtzo-floss/sanitize_email
502
+ [🚎contributors-gl]: https://gitlab.com/galtzo-floss/sanitize_email/-/graphs/main
503
+ [🪇conduct]: https://github.com/galtzo-floss/sanitize_email/blob/main/CODE_OF_CONDUCT.md
504
+ [🪇conduct-img]: https://img.shields.io/badge/Contributor_Covenant-2.1-259D6C.svg
505
+ [📌pvc]: http://guides.rubygems.org/patterns/#pessimistic-version-constraint
506
+ [📌semver]: https://semver.org/spec/v2.0.0.html
507
+ [📌semver-img]: https://img.shields.io/badge/semver-2.0.0-259D6C.svg?style=flat
508
+ [📌semver-breaking]: https://github.com/semver/semver/issues/716#issuecomment-869336139
509
+ [📌major-versions-not-sacred]: https://tom.preston-werner.com/2022/05/23/major-version-numbers-are-not-sacred.html
510
+ [📌changelog]: https://github.com/galtzo-floss/sanitize_email/blob/main/CHANGELOG.md
511
+ [📗keep-changelog]: https://keepachangelog.com/en/1.0.0/
512
+ [📗keep-changelog-img]: https://img.shields.io/badge/keep--a--changelog-1.0.0-34495e.svg?style=flat
513
+ [📌gitmoji]: https://gitmoji.dev
514
+ [📌gitmoji-img]: https://img.shields.io/badge/gitmoji_commits-%20%F0%9F%98%9C%20%F0%9F%98%8D-34495e.svg?style=flat-square
515
+ [🧮kloc]: https://www.youtube.com/watch?v=dQw4w9WgXcQ
516
+ [🧮kloc-img]: https://img.shields.io/badge/KLOC-0.273-FFDD67.svg?style=for-the-badge&logo=YouTube&logoColor=blue
517
+ [🔐security]: https://github.com/galtzo-floss/sanitize_email/blob/main/SECURITY.md
518
+ [🔐security-img]: https://img.shields.io/badge/security-policy-259D6C.svg?style=flat
519
+ [📄copyright-notice-explainer]: https://opensource.stackexchange.com/questions/5778/why-do-licenses-such-as-the-mit-license-specify-a-single-year
520
+ [📄license]: LICENSE.md
521
+ [📄license-ref]: MIT.md
522
+ [📄license-img]: https://img.shields.io/badge/License-MIT-259D6C.svg
523
+ [📄license-compat]: https://www.apache.org/legal/resolved.html#category-a
524
+ [📄license-compat-img]: https://img.shields.io/badge/Apache_Compatible:_Category_A-%E2%9C%93-259D6C.svg?style=flat&logo=Apache
525
+
526
+ [📄ilo-declaration]: https://www.ilo.org/declaration/lang--en/index.htm
527
+ [📄ilo-declaration-img]: https://img.shields.io/badge/ILO_Fundamental_Principles-✓-259D6C.svg?style=flat
528
+ [🚎yard-current]: http://rubydoc.info/gems/sanitize_email
529
+ [🚎yard-head]: https://sanitize-email.galtzo.com
530
+ [💎stone_checksums]: https://github.com/galtzo-floss/stone_checksums
531
+ [💎SHA_checksums]: https://gitlab.com/galtzo-floss/sanitize_email/-/tree/main/checksums
532
+ [💎rlts]: https://github.com/rubocop-lts/rubocop-lts
533
+ [💎rlts-img]: https://img.shields.io/badge/code_style_&_linting-rubocop--lts-34495e.svg?plastic&logo=ruby&logoColor=white
534
+ [💎appraisal2]: https://github.com/appraisal-rb/appraisal2
535
+ [💎appraisal2-img]: https://img.shields.io/badge/appraised_by-appraisal2-34495e.svg?plastic&logo=ruby&logoColor=white
536
+ [💎d-in-dvcs]: https://railsbling.com/posts/dvcs/put_the_d_in_dvcs/
537
+
538
+ <!-- kettle-jem:metadata:start -->
539
+ | Field | Value |
540
+ |---|---|
541
+ | Package | sanitize_email |
542
+ | 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. |
543
+ | Homepage | https://github.com/galtzo-floss/sanitize_email |
544
+ | Source | https://github.com/galtzo-floss/sanitize_email/tree/v2.0.11 |
545
+ | License | `MIT` |
546
+ | Funding | https://github.com/sponsors/pboling, https://issuehunt.io/u/pboling, https://ko-fi.com/pboling, https://liberapay.com/pboling/donate, https://opencollective.com/galtzo-floss, 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 |
547
+ <!-- kettle-jem:metadata:end -->