├── LICENSE ├── README.md ├── etc ├── .gitkeep ├── postfix │ ├── .gitkeep │ ├── main.cf │ └── master.cf └── selinux │ ├── .gitkeep │ └── postfix-lh.te ├── how-it-works ├── .gitkeep └── AUTOMATIC_EMAIL_ENCRYPTION_v01.png ├── usr ├── .gitkeep └── local │ ├── .gitkeep │ └── bin │ ├── .gitkeep │ └── bash-postfix-encrypt-filter.sh └── var ├── .gitkeep └── spool ├── .gitkeep └── bash-postfix-encrypt ├── .gitkeep ├── archive └── .gitkeep ├── exceptions_encrypt_from.txt ├── exceptions_encrypt_to.txt ├── log ├── .gitkeep └── bash-postfix-encrypt-filter.log ├── pgp └── .gitkeep ├── smime └── .gitkeep └── work └── .gitkeep /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Automatic Email Encryption for Postfix 2 | **Date:** 2019 3 | **Author:** Ladislav Hajzer 4 | 5 | 6 | ## Content 7 | * [About](#about) 8 | * [How it works](#How-it-works) 9 | * [Example - S/MIME email message](#example-smime-email-message) 10 | * [Example - PGP/MIME email message](#example-pgpmime-email-message) 11 | * [Example - Informational email message](#example-informational-email-message) 12 | * [Installation](#installation) 13 | 14 | 15 | ## About 16 | This is a postfix content filter written in BASH scripting language which automatically encrypt email messages with email encryption standards as S/MIME and PGP/MIME. 17 | 18 | 19 | ## How it works 20 | 1. Internal email server receive email message from some application/system thru SMTP (with TLS) or SMTPS. 21 | 2. Email message goes to Postfix "input" queue. 22 | 3. Email message goes to Postfix content filter (BASH-POSTFIX-ENCRYPT-FILTER). 23 | > Note: If original email has multiple recipients (MAIL TO:), then email server Postfix will generate single recipient emails which are then passed to the Postfix content filter. For example, if original (unmodified) email will have three recipients, postfix will create three emails with single recipient and those three emails are then passed separatelly to the Postfix content filter. 24 | 25 | 4. BASH-POSTFIX-ENCRYPT-FILTER analyze email header **MAIL FROM:** and compared with list of exceptions. If sender/source email address is listed in encryption exception list then original email message is forwarded (unmodified) to Postfix "output" queue. 26 | 5. BASH-POSTFIX-ENCRYPT-FILTER analyze email header **RCP TO:** and compared with list of exceptions. If recipient/destination email address is listed in encryption exception list then original email message is forwarded (unmodified) to Postfix "output" queue. 27 | 6. BASH-POSTFIX-ENCRYPT-FILTER check if S/MIME public certificate is stored (as file) in directory structure of BASH-POSTFIX-ENCRYPT-FILTER (/var/spool/postfix/bash-postfix-encrypt-filter/smime). 28 | > Note: If S/MIME certificate is present then S/MIME encryption is possible. 29 | 30 | 7. BASH-POSTFIX-ENCRYPT-FILTER check if PGP public key is stored (as file) in directory structure of BASH-POSTFIX-ENCRYPT-FILTER (/var/spool/postfix/bash-postfix-encrypt-filter/pgp). 31 | > Note: If PGP/GPG public key is present then PGP/MIME encryption is possible. 32 | 33 | 8. If BASH-POSTFIX-ENCRYPT-FILTER is unable to encrypt email with S/MIME or PGP/MIME then original email body is modified original content is replaced with information email with information that email cannot be encrypted and with information where to send S/MIME public certificate or PGP/GPG public key. 34 | > Note: Example of modified email body is in the section "Example - Informational email message". 35 | 36 | 9. If BASH-POSTFIX-ENCRYPT-FILTER can create S/MIME or PGP/MIME encrypted email from original email message, then encrypted email is created and then forwarded to Postfix "output" queue. 37 | 38 | 39 |  40 | 41 | 42 | ## Example - S/MIME email message 43 |
44 | To: dst-email@domain1.com 45 | From: test@test.sk 46 | Subject: TESTING email 47 | MIME-Version: 1.0 48 | Content-Disposition: attachment; filename="smime.p7m" 49 | Content-Type: application/x-pkcs7-mime; smime-type=enveloped-data; name="smime.p7m" 50 | Content-Transfer-Encoding: base64 51 | 52 | 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 133 | utc= 134 |135 | 136 | 137 | ## Example - PGP/MIME email message 138 |
139 | Date: Wed, 14 Nov 2018 13:33:14 +0100 140 | From: test@test.sk 141 | Subject: TESTING email 142 | MIME-Version: 1.0 143 | To: dst-email@domain2.net 144 | Content-Type: multipart/encrypted; boundary=74c39984-e809-11e8-80f8-00163e000017; protocol="application/pgp-encrypted" 145 | 146 | --74c39984-e809-11e8-80f8-00163e000017 147 | Content-Type: application/pgp-encrypted 148 | Content-Description: PGP/MIME version identification 149 | 150 | Version: 1 151 | 152 | --74c39984-e809-11e8-80f8-00163e000017 153 | Content-Type: application/octet-stream; name="encrypted.asc" 154 | Content-Description: OpenPGP encrypted message 155 | Content-Disposition: inline; filename="encrypted.asc" 156 | 157 | -----BEGIN PGP MESSAGE----- 158 | Version: GnuPG v2.0.22 (GNU/Linux) 159 | 160 | hQIMA0VpDUosV+vSARAAjqahPx/dkB1N5+VRwrQZ6Ik7vhubchxxXSY65AGK9llf 161 | 7UTVwmLvSx9uadw1s7wKZqtlP+jlctvDk8DgbuM6MXVaCWLFg2q4dKNV5yAneBDT 162 | TKLuAXFhlJfdGyI3fozEfTCf7GH/cBHwRbTnzyJY9lHyJvRIg8tng+ekII6gX2eR 163 | 2GnJD6sjqfrRLnjpZdTQfL8nX9ZFVnbf3j5IMjpo3tSAPWNHkKAIYsUYyK8OlK7x 164 | fOHXTqdJMNAG1bOpvSN1/i9wmIval6hbHXfPcNuC/1yLYLQ13k8FgZMwmxO58h5+ 165 | +CGrOGuj6m5a2zHRaj3UDO0ITZpzcAG6QD4T4n9/8z0tQdjoZzuCU/VnwWevynw5 166 | Xxf6UOf9KJvb/Onu7tVlbVB/opLYLsnlZDVSfhN7/5Kcpfc+IVu2ewbQs3ud2NMg 167 | FON/m/av0fgFhTplVuEdJVUYwcBDvzgfE36Pu9l2IIRHP8OY8hs2HcR6cRbMrKaL 168 | zzJUoshHcbKj1YOBzZhFKZtO1CImR1j48P3rDjutVtdT1KPJjeBswfH//aTRhLqL 169 | vruGHjlCAyHAWnT3GhvPQRYYW8dR8BtWUe1N2GQkgojA6TzaSUvvZbNd8eiJuZ6O 170 | Y3ulR27gfxwM8t3Gm57BXC6H64EaGvwfPA0NxzlO0JwUcHRq8RAepr9JQPhiQ83S 171 | 6gE8qYT4kk0IsfVAYALXqLJBIKeu5bVDTEpQBZ9kKGDVpseF7h8IuJFwcAGGSpSn 172 | sJDPxKwcHdF+wKaypQ+8X5As23TgLedotNoml4e1cI0kyOQCeYG+M1Nzt56G0o4M 173 | PbtZoF1S7RqjDtEVJ5N6wIYUL9iJlWjr9ZPBIUYadGbhkxAv9D4DZ9Nnhuf3UI/R 174 | SBYgR9lyeU6A72z6yOQKdQvZfCz2ZkLbyNpthXvN7QvhP+QAqvemwBz3VViwrkiI 175 | mwQsxO+/NENOAgdqlvRdpzyFNIuE3gv895CVfuFfsXkCMgP4SG9tDd1+GvyWrPuZ 176 | gjkmPqA9f2cmiF6aMdpmvtJd5mq5t605sOQMb25dPosCkFyiLj/nHl6UI/hxjWgD 177 | EHnzuY48KaCep0NHDlWOvpQgiDloB9m2FXTWRWUw7UXqVql3QEkgVfsFZw65+4Q4 178 | SG754SHndDtu24nGaGKrXbqVFGAZQPxoXw/pm1FWpPASy3ERsd+/XxW+ni4yzdAJ 179 | QDoOIhvvZVqvEsAxpotlXK93OoDivjhCBNrOW0QKfkn6Dp7+FBsHOBIn1B8fIlWH 180 | 9YCbpj7nApPYx67g7s+qHChVwDmk9jGYQwrODd0jGayHInGXuIRXEr79mY6JSwMD 181 | KEFm31uiYNULadNA1GQt5HwjvObfUZVGwSuYYDOwtaO/jxACbRtOUrEx01Z1rqSA 182 | EFjA3Vfm99Tki++6kvLYwS3IIIVO5Vge5RHnUet3aDcud33DW42tQphNefjhpSKa 183 | BeHKEl/YeedvRrpejvyy0sb8CpF6nIgN9vRlFz+CBkJJ4f49J15ZrvtmDnFRBTB8 184 | SzlIFxiLb/0PtKf1gfoowBhRWSbAYXxQ2jbNu5y2JyD2CxccI0dEz74bGorzXCkz 185 | mzrpoEdy0FT49hTutcy/SJ33rXtEJdEnxJ2215vNqVgtx/oJlOxXp+Ug1LMM1DG7 186 | mss0nvlDhGR6qk2meuSXfg7pq4q1gRKRJhaCePk0mQZKAhN/vkrN+TUM+z9qUxk0 187 | Ky+xYz4mCbgmyeczgenc6CfyxytP+Hrjg4CgLXSd0itpcBEJXwopPFaTJqtEFOzl 188 | jcneC6Lj5hSpLvxzwMFEPCVJqzDz7MnPCARenaekzTDFQ8uNpBAJnNFEB1e1g004 189 | VTS8HrxaHl/OPgtQUrhDwL1SACfx+R2lT7IirbmKJySo33E5sAY0KMJHx3JbNXiZ 190 | wVLD3eu7siBLid+WFpJa6pP8PjTcv2LrO46ghJ8PImc7jjA1PEQv4Lt1/SrcVqQJ 191 | 1gxnpJqC0dATMbzZzQ/IDx1q5vOo9ShMk2qq1YhneC12t6mr/P8vt0QnDK/U7hCn 192 | MeMYji9hiiknFhPlbHg7cbvAiYi1a7+e77+a2Myn33XuwVq0ULNWJffXDG15+Nvb 193 | VX4rDXLhaBv/UGcfsyfIizlBi4moz8sbKNNXWEcX2KL1SYNe9Ct9t/k4W0zStQI+ 194 | 9vgqyH7DHmUs2YSNYmOYLEeo9S7XBKuAjDzSBQ5zAxOFaJucslO0My6AW/lUT9/t 195 | xKXNzNXtjydcufITqjl04cnPXgeWbuVFoBTz7EgUy846YEvki4S401i+KJuveNAM 196 | /tgK6+ACnxQAXLkyfgvd27zzeaPFt6aTMcBvft/M5tImavFoWU58y7nGof7EJDm9 197 | JYF+gETzFxQVgYQ3Q3w9GJ0pf7OQjWwp5/Gi/G1zF2lO6cp0ZOBkruB3y+NuRGbO 198 | 79ShPd9awXXYysQWffeeFkPOlzcF2gfaoMVm4NUdBkrlsqt2U/LYHwXvTj9fSn2M 199 | N+zfkzvyEHmgP5RU 200 | =EGTW 201 | -----END PGP MESSAGE----- 202 | 203 | --74c39984-e809-11e8-80f8-00163e000017 204 |205 | 206 | 207 | ## Example - Informational email message 208 |
209 | From test@test.sk Wed Nov 14 13:33:14 2018 210 | Received: from system.this-domain.com (localhost [127.0.0.1]) 211 | by mail.this-domain.com (Postfix) with SMTP id 850D31470; 212 | Wed, 14 Nov 2018 13:33:14 +0100 (CET) 213 | Date: Wed, 14 Nov 2018 13:33:14 +0100 214 | From: test@test.sk 215 | Subject: TESTING email 216 | Message-ID: <5bec160a.p3HuVox6szultDqc%test@test.sk> 217 | User-Agent: Heirloom mailx 12.5 7/5/10 218 | MIME-Version: 1.0 219 | Content-Type: multipart/mixed; 220 | boundary="=_5bec160a.NhKsITer09OFhaPH0MGOj6MhS0/HQIyVVyeMGfiNr1Jd8S4g" 221 | To: lala@linuxor.sk 222 | 223 | Dear recipient, 224 | 225 | email message from address 'test@test.sk' was targeted to your address 'lala@linuxor.sk', but our email system don't have your S/MIME certificate or PGP/GPG public key. If you want to receive encrypted messages please send your S/MIME certificate or PGP/GPG public key to email address smime_pgp@this-domain.com. 226 | 227 | Thank you for your understanding and cooperation. 228 | 229 | Best regards 230 | This-domain.com team 231 |232 | 233 | ## Installation 234 | 235 | 0. Install prerequizities/dependencies. 236 |
237 | # yum install openssl gnupg2 procmail awk 238 |239 | 240 | 241 | 1. Add user for content filter. 242 |
243 | # useradd bash-postfix-encrypt-filter 244 |245 | 246 | 247 | 2. Upload the script to email server and copy to desired directory + set correct owner and persmissions. 248 |
249 | # cp /tmp/bash-postfix-encrypt-filter.sh /usr/local/bin/ 250 | # chown bash-postfix-encrypt-filter:root /usr/local/bin/bash-postfix-encrypt-filter.sh 251 | # chmod 500 /usr/local/bin/bash-postfix-encrypt-filter.sh 252 |253 | 254 | 255 | 3. Create directory structure for content filter + set correct owner and permissions. 256 |
257 | # mkdir -p /var/spool/postfix/bash-postfix-encrypt-filter 258 | # mkdir -p /var/spool/postfix/bash-postfix-encrypt-filter/archive 259 | # mkdir -p /var/spool/postfix/bash-postfix-encrypt-filter/log 260 | # mkdir -p /var/spool/postfix/bash-postfix-encrypt-filter/pgp 261 | # mkdir -p /var/spool/postfix/bash-postfix-encrypt-filter/smime 262 | # mkdir -p /var/spool/postfix/bash-postfix-encrypt-filter/work 263 | # chown -R bash-postfix-encrypt-filter:root /var/spool/postfix/bash-postfix-encrypt-filter/ 264 | # chmod -R 700 /var/spool/postfix/bash-postfix-encrypt-filter 265 |266 | 267 | 268 | 4. Create file with sender (**MAIL FROM:**) email addresses as encryption exception list + set correct owner and permissions. 269 |
270 | # vi /var/spool/postfix/bash-postfix-encrypt-filter/exceptions_encrypt_from.txt 271 | -------------------------------------------------------------------------------- 272 | mailer-daemon@this-domain.com 273 | src-exception1@this-domain.com 274 | src-exception2@this-domain.com 275 | ---------------------------------------------------------------------------------------------------- 276 | # chown -R bash-postfix-encrypt-filter:root /var/spool/postfix/bash-postfix-encrypt-filter/exceptions_encrypt_from.txt 277 | # chmod -R 400 /var/spool/postfix/bash-postfix-encrypt-filter/exceptions_encrypt_from.txt 278 |279 | 280 | 281 | 5. Create file with recipient (**RCPT TO:**) email addresses as encryption exception list + set correct owner and permissions. 282 |
283 | # vi /var/spool/postfix/bash-postfix-encrypt-filter/exceptions_encrypt_to.txt 284 | -------------------------------------------------------------------------------- 285 | @this-domain.com 286 | ---------------------------------------------------------------------------------------------------- 287 | # chown -R bash-postfix-encrypt-filter:root /var/spool/postfix/bash-postfix-encrypt-filter/exceptions_encrypt_to.txt 288 | # chmod -R 400 /var/spool/postfix/bash-postfix-encrypt-filter/exceptions_encrypt_to.txt 289 |290 | 291 | 292 | 6. Define and enable encrypt filter. 293 |
294 | # vi /etc/postfix/master.cf 295 | -------------------------------------------------------------------------------- 296 | # Definition of BASH postfix encrypt filter 297 | bash-postfix-encrypt-filter unix - n n - - pipe 298 | flags=Rq user=bash-postfix-encrypt-filter null_sender= 299 | argv=/usr/local/bin/bash-postfix-encrypt-filter.sh -f ${sender} -- ${recipient} 300 | # Enable BASH postfix encrypt filter for SMTP only 301 | smtp inet n - n - - smtpd 302 | -o content_filter=bash-postfix-encrypt-filter: 303 | # Enable BASH postfix encrypt filter for SMTPS only 304 | smtps inet n - n - - smtpd 305 | -o syslog_name=postfix/smtps 306 | -o smtpd_tls_wrappermode=yes 307 | -o smtpd_sasl_auth_enable=yes 308 | -o smtpd_reject_unlisted_recipient=no 309 | -o smtpd_recipient_restrictions=permit_sasl_authenticated,reject 310 | -o milter_macro_daemon_name=ORIGINATING 311 | -o content_filter=bash-postfix-encrypt-filter: 312 |313 | 314 | 315 | 7. Set maximal number of recipiemts per message delivery for encrypt filter transport. 316 |
317 | # vi /etc/postfix/main.cf 318 | -------------------------------------------------------------------------------- 319 | # Set the maximal number of recipients per message delivery for transport "bash-encrypt-content-filter". 320 | # Setting this parameter to a value of 1 affects email deliveries as follows: 321 | # - It changes the meaning of the corresponding per-destination concurrency limit, from concurrency 322 | # of deliveries to the same domain into concurrency of deliveries to the same recipient. Different 323 | # recipients are delivered in parallel, subject to the process limits specified in master.cf. 324 | # - It changes the meaning of the corresponding per-destination rate delay, from the delay between 325 | # deliveries to the same domain into the delay between deliveries to the same recipient. Again, 326 | # different recipients are delivered in parallel, subject to the process limits specified in master.cf. 327 | # - It changes the meaning of other corresponding per-destination settings in a similar manner, from 328 | # settings for delivery to the same domain into settings for delivery to the same recipient. 329 | # 330 | # REF1: http://www.postfix.org/postconf.5.html#default_destination_recipient_limit 331 | # REF2: http://www.postfix.org/postconf.5.html#transport_destination_recipient_limit 332 | bash-postfix-encrypt-filter_destination_recipient_limit=1 333 |334 | 335 | 336 | 8. Deploy SeLinux policy for postfix daemon with rules for this content filter. 337 |
338 | # vi /etc/selinux/postfix-lh.te 339 | -------------------------------------------------------------------------------- 340 | module postfix-lh 1.0; 341 | 342 | require { 343 | type var_t; 344 | type system_mail_t; 345 | type postfix_spool_t; 346 | type postfix_pipe_t; 347 | type gpg_exec_t; 348 | type gpg_agent_exec_t; 349 | class dir { create add_name remove_name write rmdir }; 350 | class file { create execute execute_no_trans getattr link lock open read rename setattr unlink write }; 351 | } 352 | 353 | #============= postfix_pipe_t ============== 354 | allow postfix_pipe_t gpg_agent_exec_t:file { execute read }; 355 | allow postfix_pipe_t gpg_exec_t:file { execute execute_no_trans open read }; 356 | allow postfix_pipe_t postfix_spool_t:dir { create add_name remove_name write rmdir }; 357 | allow postfix_pipe_t postfix_spool_t:file { create open write read getattr unlink }; 358 | allow postfix_pipe_t var_t:dir { add_name remove_name write }; 359 | allow postfix_pipe_t var_t:file { create getattr link lock open read rename setattr unlink write }; 360 | 361 | #============= system_mail_t ============== 362 | allow system_mail_t postfix_spool_t:file { getattr read }; 363 |364 | 365 | 366 | 9. Convert type enforcement file (.te) into a policy module (.mod). 367 |
368 | # cd /etc/selinux 369 | # checkmodule -M -m -o postfix-lh.mod postfix-lh.te 370 |371 | 372 | 373 | 10. Compile policy module (.mod) into policy package (.pp). 374 |
375 | # semodule_package -o postfix-lh.pp -m postfix-lh.mod 376 |377 | 378 | 379 | 11. Load SeLinux Policy Package module **"postfix-lh.pp"** into running system. 380 |
381 | # semodule -i postfix-lh.pp 382 |383 | 384 | 385 | 12. Upload SMIME certificates in the form **"email@address.com.cer"** to SMIME directory (*/var/spool/postfix/bash-postfix-encrypt-filter/pgp*) for each recipient email address for which is needed to encrypt email messsage + set correct owner and permissions. 386 |
387 | # cp /tmp/email@address.com.cer /var/spool/postfix/bash-postfix-encrypt-filter/smime/ 388 | # chown -R bash-postfix-encrypt-filter:root /var/spool/postfix/bash-postfix-encrypt-filter/smime/email@address.com.cer 389 | # chmod -R 400 /var/spool/postfix/bash-postfix-encrypt-filter/smime/email@address.com.cer 390 |391 | 392 | 393 | 13. Upload PGP/GPG public key in the form **"email@address.com.asc"** to PGP directory (*/var/spool/postfix/bash-postfix-encrypt-filter/pgp*) for each recipient email address for which is needed to encrypt email messsage + set correct owner and permissions. 394 |
395 | # cp /tmp/email@address.com.asc /var/spool/postfix/bash-postfix-encrypt-filter/pgp/ 396 | # chown -R bash-postfix-encrypt-filter:root /var/spool/postfix/bash-postfix-encrypt-filter/pgp/email@address.com.asc 397 | # chmod -R 400 /var/spool/postfix/bash-postfix-encrypt-filter/pgp/email@address.com.asc 398 |399 | -------------------------------------------------------------------------------- /etc/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hajzer/bash-postfix-encrypt-filter/138ae1a67812b5c3f1d050f558c55708d7a405b0/etc/.gitkeep -------------------------------------------------------------------------------- /etc/postfix/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hajzer/bash-postfix-encrypt-filter/138ae1a67812b5c3f1d050f558c55708d7a405b0/etc/postfix/.gitkeep -------------------------------------------------------------------------------- /etc/postfix/main.cf: -------------------------------------------------------------------------------- 1 | # Global Postfix configuration file. This file lists only a subset 2 | # of all parameters. For the syntax, and for a complete parameter 3 | # list, see the postconf(5) manual page (command: "man 5 postconf"). 4 | # 5 | # For common configuration examples, see BASIC_CONFIGURATION_README 6 | # and STANDARD_CONFIGURATION_README. To find these documents, use 7 | # the command "postconf html_directory readme_directory", or go to 8 | # http://www.postfix.org/. 9 | # 10 | # For best results, change no more than 2-3 parameters at a time, 11 | # and test if Postfix still works after every change. 12 | 13 | ... 14 | 15 | # Set the maximal number of recipients per message delivery for transport "bash-encrypt-content-filter". 16 | # Setting this parameter to a value of 1 affects email deliveries as follows: 17 | # - It changes the meaning of the corresponding per-destination concurrency limit, from concurrency 18 | # of deliveries to the same domain into concurrency of deliveries to the same recipient. Different 19 | # recipients are delivered in parallel, subject to the process limits specified in master.cf. 20 | # - It changes the meaning of the corresponding per-destination rate delay, from the delay between 21 | # deliveries to the same domain into the delay between deliveries to the same recipient. Again, 22 | # different recipients are delivered in parallel, subject to the process limits specified in master.cf. 23 | # - It changes the meaning of other corresponding per-destination settings in a similar manner, from 24 | # settings for delivery to the same domain into settings for delivery to the same recipient. 25 | # 26 | # REF1: http://www.postfix.org/postconf.5.html#default_destination_recipient_limit 27 | # REF2: http://www.postfix.org/postconf.5.html#transport_destination_recipient_limit 28 | bash-postfix-encrypt-filter_destination_recipient_limit=1 29 | 30 | -------------------------------------------------------------------------------- /etc/postfix/master.cf: -------------------------------------------------------------------------------- 1 | # 2 | # Postfix master process configuration file. For details on the format 3 | # of the file, see the master(5) manual page (command: "man 5 master"). 4 | # 5 | # Do not forget to execute "postfix reload" after editing this file. 6 | # 7 | # ========================================================================== 8 | # service type private unpriv chroot wakeup maxproc command + args 9 | # (yes) (yes) (yes) (never) (100) 10 | # ========================================================================== 11 | # Definition of BASH postfix encrypt filter 12 | bash-postfix-encrypt-filter unix - n n - - pipe 13 | flags=q user=bash-postfix-encrypt-filter null_sender= 14 | argv=/usr/local/bin/bash-postfix-encrypt-filter.sh -f ${sender} -- ${recipient} 15 | smtp inet n - n - - smtpd 16 | -o content_filter=bash-postfix-encrypt-filter: 17 | 18 | 19 | -------------------------------------------------------------------------------- /etc/selinux/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hajzer/bash-postfix-encrypt-filter/138ae1a67812b5c3f1d050f558c55708d7a405b0/etc/selinux/.gitkeep -------------------------------------------------------------------------------- /etc/selinux/postfix-lh.te: -------------------------------------------------------------------------------- 1 | module postfix-lh 1.0; 2 | 3 | require { 4 | type var_t; 5 | type var_log_t; 6 | type system_mail_t; 7 | type postfix_spool_t; 8 | type postfix_pipe_t; 9 | type logrotate_t; 10 | type gpg_exec_t; 11 | type gpg_agent_exec_t; 12 | class dir { create read add_name remove_name write rmdir }; 13 | class file { create execute execute_no_trans getattr link lock open read rename setattr unlink write append }; 14 | } 15 | 16 | #============= postfix_pipe_t ============== 17 | allow postfix_pipe_t gpg_agent_exec_t:file { execute read }; 18 | allow postfix_pipe_t gpg_exec_t:file { execute execute_no_trans open read }; 19 | allow postfix_pipe_t postfix_spool_t:dir { create add_name remove_name write rmdir }; 20 | allow postfix_pipe_t postfix_spool_t:file { create open write read getattr unlink }; 21 | allow postfix_pipe_t var_t:dir { add_name remove_name write }; 22 | allow postfix_pipe_t var_log_t:file { create getattr link lock open read rename setattr unlink write append }; 23 | 24 | #============= system_mail_t ============== 25 | allow system_mail_t postfix_spool_t:file { getattr read }; 26 | 27 | #============= logrotate_t ============== 28 | allow logrotate_t postfix_spool_t:dir read; 29 | allow logrotate_t postfix_spool_t:file { create getattr link lock open read rename setattr unlink write }; 30 | -------------------------------------------------------------------------------- /how-it-works/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hajzer/bash-postfix-encrypt-filter/138ae1a67812b5c3f1d050f558c55708d7a405b0/how-it-works/.gitkeep -------------------------------------------------------------------------------- /how-it-works/AUTOMATIC_EMAIL_ENCRYPTION_v01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hajzer/bash-postfix-encrypt-filter/138ae1a67812b5c3f1d050f558c55708d7a405b0/how-it-works/AUTOMATIC_EMAIL_ENCRYPTION_v01.png -------------------------------------------------------------------------------- /usr/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hajzer/bash-postfix-encrypt-filter/138ae1a67812b5c3f1d050f558c55708d7a405b0/usr/.gitkeep -------------------------------------------------------------------------------- /usr/local/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hajzer/bash-postfix-encrypt-filter/138ae1a67812b5c3f1d050f558c55708d7a405b0/usr/local/.gitkeep -------------------------------------------------------------------------------- /usr/local/bin/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hajzer/bash-postfix-encrypt-filter/138ae1a67812b5c3f1d050f558c55708d7a405b0/usr/local/bin/.gitkeep -------------------------------------------------------------------------------- /usr/local/bin/bash-postfix-encrypt-filter.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | ################################################################################## 3 | # BASH Postfix Encrypt Filter 4 | ################################################################################## 5 | # 6 | # FILE : bash-postfix-encrypt-filter.sh 7 | # AUTHOR : Ladislav Hajzer 8 | # DATE : 2019 9 | # VERSION : 0.1 10 | # HISTORY : 11 | # 0.1 - Initial version with S/MIME and PGP/MIME support 12 | # 13 | # TODO : 14 | # - Exception list with grep (need to perform benchmark). Cons of using grep is new dependency. 15 | # - Refactoring 16 | # 17 | ################################################################################## 18 | # SCRIPT USER SETTINGS 19 | ################################################################################## 20 | 21 | # 22 | # ARCHIVING 23 | # 24 | # ARCHIVE_ORIGINAL - Enable (1) or disable (0) archiving of input clear email messages 25 | # ARCHIVE_ENCRYPTED - Enable (1) or disable (0) archiving of output encrypted email messages 26 | # ARCHIVE_RETENTION - Specify (in days) retention of archived email messages. 27 | # 28 | ARCHIVE_ORIGINAL=1 29 | ARCHIVE_ENCRYPTED=1 30 | ARCHIVE_RETENTION=1 31 | 32 | # 33 | # ENCRYPTION 34 | # 35 | # ENCRYPT_PREFERENCE - Set encryption preference to SMIME (smime) or PGP (pgp). 36 | # ENCRYPT_EXCEPTIONS_FROM - List of sender/source email addresses as exceptions for encryption. 37 | # ENCRYPT_EXCEPTIONS_TO - List of recipient/destination email addresses as exceptions for encryption. 38 | # 39 | ENCRYPT_PREFERENCE="smime" 40 | ENCRYPT_EXCEPTIONS_FROM="/var/spool/postfix/bash-postfix-encrypt-filter/exceptions_encrypt_from.txt" 41 | ENCRYPT_EXCEPTIONS_TO="/var/spool/postfix/bash-postfix-encrypt-filter/exceptions_encrypt_to.txt" 42 | 43 | # 44 | # LOGGING 45 | # 46 | # LOGGING_ENABLED - Enable (1) or disable (0) logging to file specified by LOGGING_FILE variable. 47 | # LOGGING_DATE_FORMAT - Logging date format (for syntax -> man date) 48 | # 49 | LOGGING_ENABLED=1 50 | LOGGING_DATE_FORMAT="%Y-%m-%d %H:%M:%S (%Z)" 51 | 52 | 53 | ################################################################################## 54 | # INITIALIZATION 55 | ################################################################################## 56 | 57 | # 58 | # Email variables 59 | # 60 | INSPECT_EMAIL_ID=$$ 61 | INSPECT_EMAIL_FROM="$(echo $2 | tr '[A-Z]' '[a-z]')" 62 | INSPECT_EMAIL_TO="$(echo $4 | tr '[A-Z]' '[a-z]')" 63 | 64 | # 65 | # Encryption 66 | # 67 | ENCRYPT_SMIME_POSSIBLE=0 68 | ENCRYPT_PGP_POSSIBLE=0 69 | 70 | 71 | ################################################################################## 72 | # SCRIPT INTERNAL SETTINGS 73 | ################################################################################## 74 | 75 | # 76 | # SCRIPT DIRECTORIES 77 | # 78 | DIRECTORY_BASE="/var/spool/postfix/bash-postfix-encrypt-filter" 79 | DIRECTORY_WORK="$DIRECTORY_BASE/work" 80 | DIRECTORY_PGP="$DIRECTORY_BASE/pgp" 81 | DIRECTORY_SMIME="$DIRECTORY_BASE/smime" 82 | DIRECTORY_ARCHIVE="$DIRECTORY_BASE/archive" 83 | DIRECTORY_LOGGING="$DIRECTORY_BASE/log" 84 | 85 | # 86 | # SCRIPT LOGGING FILE 87 | # 88 | LOGGING_FILE="$DIRECTORY_LOGGING/bash-postfix-encrypt-filter.log" 89 | 90 | # 91 | # INITIALIZATION OF TEMPORARY VARIABLES FOR INSPECTION 92 | # 93 | INSPECT_DIRECTORY="$DIRECTORY_WORK/$INSPECT_EMAIL_ID" 94 | INSPECT_EMAIL_ORIGINAL="$INSPECT_DIRECTORY/in.$INSPECT_EMAIL_ID" 95 | INSPECT_EMAIL_BACKUP="$INSPECT_EMAIL_ORIGINAL.bck" 96 | INSPECT_EMAIL_ENCRYPTED="$INSPECT_DIRECTORY/in.$INSPECT_EMAIL_ID.enc" 97 | INSPECT_EMAIL_INFORMATION="$INSPECT_DIRECTORY/in.$INSPECT_EMAIL_ID.inf" 98 | INSPECT_EMAIL_TO_SMIME="$DIRECTORY_SMIME/$INSPECT_EMAIL_TO.cer" 99 | INSPECT_EMAIL_TO_PGP="$DIRECTORY_PGP/$INSPECT_EMAIL_TO.asc" 100 | 101 | # 102 | # SCRIPT MESSAGES 103 | # 104 | MESSAGE_INSPECT_DIR_CANNOT_CREATE="Cannot create inspection directory '$INSPECT_DIRECTORY'." 105 | MESSAGE_INSPECT_DIR_NOEXIST="Inspection directory '$INSPECT_DIRECTORY' does not exist." 106 | MESSAGE_INSPECT_FILE_CANNOT_SAVE="Cannot save mail to file." 107 | MESSAGE_INSPECT_FILE_CANNOT_BACKUP="Cannot create backup of original message." 108 | MESSAGE_INSPECT_ENCRYPT_SMIME_PROBLEM="Cannot encrypt original message with SMIME." 109 | MESSAGE_INSPECT_ENCRYPT_PGP_PROBLEM="Cannot encrypt original message with PGP/GPG." 110 | MESSAGE_FAIL_SENDING_ORIGINAL_MAIL="MAIL-ID=$INSPECT_EMAIL_ID:Original email message for $INSPECT_EMAIL_TO failed to send." 111 | MESSAGE_FAIL_SENDING_ENCRYPTED_MAIL="MAIL-ID=$INSPECT_EMAIL_ID:Encrypted email message for $INSPECT_EMAIL_TO failed to send." 112 | MESSAGE_FAIL_SENDING_INFORMATION_MAIL="MAIL-ID=$INSPECT_EMAIL_ID:Information email message for $INSPECT_EMAIL_TO failed to send." 113 | MESSAGE_PGP_KEY_CANNOT_IMPORT="MAIL-ID=$INSPECT_EMAIL_ID:PGP/GPG public key for $INSPECT_EMAIL_TO cannot be imported." 114 | 115 | # 116 | # LOGGING MESSAGES 117 | # 118 | LOGGING_MESSAGE_INSPECT_DIR_CANNOT_CREATE="MAIL-ID=$INSPECT_EMAIL_ID:Cannot create inspection directory '$INSPECT_DIRECTORY'." 119 | LOGGING_MESSAGE_INSPECT_DIR_NOEXIST="MAIL-ID=$INSPECT_EMAIL_ID:Inspection directory '$INSPECT_DIRECTORY' does not exist." 120 | LOGGING_MESSAGE_INSPECT_FILE_CANNOT_SAVE="MAIL-ID=$INSPECT_EMAIL_ID:Cannot save mail to file." 121 | LOGGING_MESSAGE_INSPECT_FILE_CANNOT_BACKUP="MAIL-ID=$INSPECT_EMAIL_ID:Cannot create backup of original message." 122 | LOGGING_MESSAGE_INSPECT_ENCRYPT_SMIME_PROBLEM="MAIL-ID=$INSPECT_EMAIL_ID:Cannot encrypt original message with SMIME." 123 | LOGGING_MESSAGE_INSPECT_ENCRYPT_PGP_PROBLEM="MAIL-ID=$INSPECT_EMAIL_ID:Cannot encrypt original message with PGP/GPG." 124 | LOGGING_MESSAGE_MAIL_INPUT="MAIL-ID=$INSPECT_EMAIL_ID:Email message entered the filter." 125 | LOGGING_MESSAGE_MAIL_BACKUP="MAIL-ID=$INSPECT_EMAIL_ID:Creating backup of the original email message." 126 | LOGGING_MESSAGE_MAIL_SENDER_ENCRYPTION_EXCEPTION="MAIL-ID=$INSPECT_EMAIL_ID:Sender/Source email address $INSPECT_EMAIL_FROM is listed in encryption exception list = no encryption will be applied." 127 | LOGGING_MESSAGE_MAIL_RECIPIENT_ENCRYPTION_EXCEPTION="MAIL-ID=$INSPECT_EMAIL_ID:Recipient/Destination email address $INSPECT_EMAIL_TO is listed in encryption exception list = no encryption will be applied." 128 | LOGGING_MESSAGE_MAIL_RECIPIENT_CHANGE="MAIL-ID=$INSPECT_EMAIL_ID:Recipient changed to $INSPECT_EMAIL_TO." 129 | LOGGING_MESSAGE_MAIL_ENCRYPT_PREFERENCE="MAIL-ID=$INSPECT_EMAIL_ID:Global encryption preference is $ENCRYPT_PREFERENCE." 130 | LOGGING_MESSAGE_MAIL_ENCRYPT_PGP_POSSIBLE="MAIL-ID=$INSPECT_EMAIL_ID:PGP/GPG encryption for $INSPECT_EMAIL_TO is possible." 131 | LOGGING_MESSAGE_MAIL_ENCRYPT_PGP_NOT_POSSIBLE="MAIL-ID=$INSPECT_EMAIL_ID:PGP/GPG encryption for $INSPECT_EMAIL_TO is not possible!" 132 | LOGGING_MESSAGE_MAIL_ENCRYPT_SMIME_POSSIBLE="MAIL-ID=$INSPECT_EMAIL_ID:SMIME encryption for $INSPECT_EMAIL_TO is possible." 133 | LOGGING_MESSAGE_MAIL_ENCRYPT_SMIME_NOT_POSSIBLE="MAIL-ID=$INSPECT_EMAIL_ID:SMIME encryption for $INSPECT_EMAIL_TO is not possible!" 134 | LOGGING_MESSAGE_MAIL_ENCRYPTED_SMIME="MAIL-ID=$INSPECT_EMAIL_ID:Email message for $INSPECT_EMAIL_TO was successfully encrypted with SMIME." 135 | LOGGING_MESSAGE_MAIL_ENCRYPTED_PGP="MAIL-ID=$INSPECT_EMAIL_ID:Email message for $INSPECT_EMAIL_TO was successfully encrypted with PGP/GPG." 136 | LOGGING_MESSAGE_MAIL_ENCRYPTION_NOT_POSSIBLE="MAIL-ID=$INSPECT_EMAIL_ID:Email message for $INSPECT_EMAIL_TO is not possible to encrypt with SMIME or PGP/GPG." 137 | LOGGING_MESSAGE_FAIL_SENDING_ORIGINAL_MAIL="MAIL-ID=$INSPECT_EMAIL_ID:Original email message for $INSPECT_EMAIL_TO failed to send." 138 | LOGGING_MESSAGE_FAIL_SENDING_ENCRYPTED_MAIL="MAIL-ID=$INSPECT_EMAIL_ID:Encrypted email message for $INSPECT_EMAIL_TO failed to send." 139 | LOGGING_MESSAGE_FAIL_SENDING_INFORMATION_MAIL="MAIL-ID=$INSPECT_EMAIL_ID:Information email message for $INSPECT_EMAIL_TO failed to send." 140 | LOGGING_MESSAGE_SENDING_ORIGINAL_MAIL_FROM="MAIL-ID=$INSPECT_EMAIL_ID:Original email message for $INSPECT_EMAIL_TO was successfully sended (source email address is listed in encryption exception list)." 141 | LOGGING_MESSAGE_SENDING_ORIGINAL_MAIL_TO="MAIL-ID=$INSPECT_EMAIL_ID:Original email message for $INSPECT_EMAIL_TO was successfully sended (destination email address is listed in encryption exception list)." 142 | LOGGING_MESSAGE_SENDING_INFORMATION_MAIL="MAIL-ID=$INSPECT_EMAIL_ID:Information email message for $INSPECT_EMAIL_TO was successfully sended." 143 | LOGGING_MESSAGE_SENDING_ENCRYPTED_MAIL="MAIL-ID=$INSPECT_EMAIL_ID:Encrypted email message for $INSPECT_EMAIL_TO was successfully sended." 144 | LOGGING_MESSAGE_PGP_KEY_CANNOT_IMPORT="MAIL-ID=$INSPECT_EMAIL_ID:PGP/GPG public key for $INSPECT_EMAIL_TO cannot be imported." 145 | 146 | # 147 | # INFORMATION EMAIL 148 | # 149 | INFORMATION_EMAIL_BODY="Dear recipient,\n" 150 | INFORMATION_EMAIL_BODY+="\n" 151 | INFORMATION_EMAIL_BODY+="email message from address '$INSPECT_EMAIL_FROM' was targeted to your address '$INSPECT_EMAIL_TO', but our email system dont have your S/MIME certificate or PGP/GPG public key. If you want to receive encrypted messages please send your S/MIME certificate or PGP/GPG public key to email address smime_pgp@this-domain.com.\n" 152 | INFORMATION_EMAIL_BODY+="\n" 153 | INFORMATION_EMAIL_BODY+="Thank you for your understanding and cooperation.\n" 154 | INFORMATION_EMAIL_BODY+="\n" 155 | INFORMATION_EMAIL_BODY+="Best regards\n" 156 | INFORMATION_EMAIL_BODY+="This-domain.com team\n" 157 | 158 | # 159 | # EXIT CODES FROM