pax_global_header00006660000000000000000000000064140100254450014505gustar00rootroot0000000000000052 comment=33b3cee974e0f9399c7b29a45abbf5f1ba3ac995 schleuder-3.6.0/000077500000000000000000000000001401002544500134715ustar00rootroot00000000000000schleuder-3.6.0/.gitattributes000066400000000000000000000001111401002544500163550ustar00rootroot00000000000000.gitlab-ci.yml export-ignore utils/ export-ignore .gitlab/ export-ignore schleuder-3.6.0/.gitignore000066400000000000000000000002131401002544500154550ustar00rootroot00000000000000.bundle vendor *.swp db/*.sqlite3 testmails/* .pc/ coverage/ /*.gem /*.gem.sig /*.tar.gz /*.tar.gz.sig Gemfile.lock spec/list-defaults.yml schleuder-3.6.0/.rspec000066400000000000000000000000361401002544500146050ustar00rootroot00000000000000--color --require spec_helper schleuder-3.6.0/CHANGELOG.md000066400000000000000000000653511401002544500153140ustar00rootroot00000000000000Change Log ========== This project adheres to [Semantic Versioning](http://semver.org/). ## [3.6.0] / 2021-02-07 ### Added * List Option `set_reply_to_to_sender` (default: false): When enabled, the `Reply-To`-header of the emails sent from Schleuder will be set to the original sender's `Reply-To`-header. If the original sender did not supply a `Reply-To`-header, the original `From`-header will be used. (#298) * List Option `munged_from` (default: false): When enabled, the `From`-header of the emails sent from Schleuder will contain the original sender's `From`-header included in the display name. To avoid DMARC issues, the `From`-header will stay the list's address. This results in a `From`-header such as: `"sender@sender.org via list@list.org" `. ### Fixed * Improve detection of bounces and thus fixing issues with falsely detected automatic messages. (#441) * Properly validate email addresses for subscriptions. (#483 & #484) ## [3.5.3] / 2020-06-13 ### Fixed * Fix running specs on IPv6-only machines. (#472) ## [3.5.2] / 2020-06-09 ### Fixed * `x-add-key` is able to handle inline key material, followed by non-key material, like a signature included in the body. (#470) ## [3.5.1] / 2020-04-15 ### Fixed * `x-add-key` is able to handle mails with attached, quoted-printable encoded keys. Such mails might be produced by Thunderbird. (#467) ## [3.5.0] / 2020-03-30 ### Added * New option for lists to include their public keys in the headers of outgoing emails (conforming with Autocrypt, https://autocrypt.org/). Defaults to true. (#335) * Add visual separator (78 dashes) to the end of the 'pseudoheaders' block: This should help users of Apple Mail, which jams this block and the body together. Hopefully, this change makes it easier to dinstiguish both parts from each other. (#348) * `deliver_selfsent` per-list option to control whether subscribers get a copy of mail they sent themselves. (#365) * Wrap pseudo headers if longer than 78 characters. ### Fixed * Ensure UTF-8 as external encoding, convert any non-utf8 email to utf-8 or drop invalid characters. This should ensure that plain text emails in different charsets can be parsed (#409, #458, #460). Also we apply that conversion to the first text part after we parsed it for keywords, if no charset is set. This fixes #457. These changes introduce a new dependency `charlock_holmes`. * Allow Jenkins job notifications to reach lists. Before, such mails were rejected due to being "auto-submitted". * Do not recognize sudo messages as automated message. (#248) * Fixed using x-attach-listkey with emails from Thunderbird that include protected headers. * Handle incoming mails encrypted to an absent key, using symmetric encryption or containing PGP-garbage in a more graceful manner: Don't throw an exception, don't notify (and annoy) the admins, instead inform the sender of the mail how to do better. (#337) * Add missing List-Id header to notification mails sent to admins. This should help with filtering such messages, which is currently not easy to do in a reliable way. * Fix running Schleuder with ruby 2.7. * Ensure that GnuPG never asks for a passphrase, even if it wants one. (#448) * Be more precise about how many keys are in the keyring and how many are usable, when resending. (#429) * Make it more clear what happens when resending an encrypted email fails (due to missing or too many matching keys), but falling back to unencrypted resend is allowed. (#343) * Be more explicit that resending to other CC recipients has been aborted. (#265) ## [3.4.1] / 2019-09-16 ### Fixed * Do not crash on protected header emails generated by mutt (#430) * Show an error message if `refresh_keys` is called with an email address for which no list exists. * Fix recognizing keywords with "protected headers" and empty subject. Previously, if the subject was unset, keywords were not recognized and the original "protected headers" could leak. (#431) ### Changed * Filter third party signatures on user-IDs when fetching or refreshing keys to mitigate against signature flooding. This works only if the version of gpg is 2.1.15 or newer. If the version is older, an email is being sent to the superadmin each time a key is fetched or keys are refreshed. See for background information. ## [3.4.0] / 2019-02-14 ### Fixed * Stop leaking keywords to third parties by stripping HTML from multipart/alternative messages if they contain keywords. (#399) * Avoid shelling out in a test-case to avoid an occasional error occurring in CI runs that complains about invalid data in ASCII-8BIT strings. ### Changed * Update the dependency 'mail' to version 2.7.x., and allow carriage returns (CR) in test-cases as mail-2.7 puts those out. * Update the dependency 'sqlite3' to version 1.3.x. * Adapt fixtures and factories for factorybot version 5.x. * Let schleuder-code load the filter files in test-mode, avoid explicit path names (which make headaches when running tests on installed packages). ## [3.3.0] / 2018-09-04 ### Fixed * Handle missing arguments for several keywords and reply with a helpful error-message. * Send replies to keyword-usage and notices to admins regardless of the delivery-flag of their subscription. (#354) * X-UNSUBSCRIBE will refuse to unsubscribe the last admin of a list. (#357) * Handle "protected subjects" in a way that Thunderbird/Enigmail recognize. (#74) * X-SET-FINGERPRINT will not anymore allow setting an empty fingerprint. (#360) ### Added * To remove a fingerprint from a subscription one can use the new keyword X-UNSET-FINGERPRINT (#360). * Extend the pseudoheaders configuration option to support 'sig' and 'enc' as configurable and sortable fields. ### Changed * The output of the keywords 'X-ADD-KEY' and 'X-DELETE-KEY' now also show the "oneline"-format to represent keys (which includes fingerprint, primary email-address, date of generation and possible expiry). (#295) * In the response to 'X-ADD-KEY', differentiate between 'newly imported' and 'updated' keys. * Parse keywords up to the first line detected as mail content, this addresses a first part of #249. ## [3.2.3] / 2018-05-14 ### Fixed * `X-SUBSCRIBE` now in all cases correctly sets the values for admin and delivery_enabled, if they are given as third and fourth argument, respectively. * To identify broken Microsoft Exchange messages, check if the headers include 'X-MS-Exchange' instead of specific domain names. Before this, we've missed mails sent by Exchange installations not operated by Microsoft or mails with a different "originating organisation domain" than Hotmail or Outlook. (#333) * Do not anymore fail on emails containing any PGP boundaries as part of their plain text. As a sideeffect we will not anymore validate an email a second time. Hence, a message part containing an additional signature within an encrypted (and possibly signed) email won't be validated and removed. (#261) * Exit with code 1 if a CLI-subcommand was not found (#339). * Fix finding keywords in request-messages that were sent from Thunderbird/Enigmail with enabled "protected subject". * Fix leaking the "protected subject" sent from Thunderbird/Enigmail. * Error messages are converted into human readable text now, instead of giving their class-name. (#338) * Require mail-gpg >= 0.3.3, which fixes a bug that let some equal-signs disappear under specific circumstances. (#287) ### Known issues * With the current used mail library version schleuder uses, there are certain malformed emails that can't be parsed. See #334 for background. This will be fixed in future releases of the mail library. ### Added * Enable to load external filters, similar to how we allow external plugins. (#282) ### Changed * Use schleuder.org as website and team@schleuder.org as contact email. * Check environment variable if code coverage check should be executed. (#342) * Transform GPG fingerprints to upper case before saving to database. (#327) * CLI-commands that (potentially) change data now remind the system admin to check file system permission if the command was run with root privileges. (#326) ## [3.2.2] / 2018-02-06 ### Changed * Temporarily depend on the ruby-library "mail" version 2.6. 2.7.0 seems to be a rough release (broke 8bit-characters, changed newline-styles) that needs to be ironed out before we can use it. * Changed wording of error-message in case of a missing or incorrect "X-LIST-NAME"-keyword. (Thanks, anarcat!) * Keys are now shuffled before refreshing them. This randomizes the way how we are querying keyservers for updated keys to avoid fingerprinting of a list's keyring. * Be more robust when dirmngr fails while refreshing keys, especially when updating over an onion service. Fixes #309. ### Fixed * Fix handling of emails with large first mime parts. We removed the code that limited the parsing of keywords to the first 1000 lines, as that broke the handling of certain large emails. * Fix output of Keys with a broken character set. This mainly affected schleuder-api. * Exit install-script if setting up the database failed. * Reveal less errors to public, and improve messages to admins. Previously errors about list-config etc. would have been included in bounces to the sender of the incoming email. Now only the admins get to know the details (which now also include the list the error happened with). Email-bounces only tell about a fatal error — except if the list could not be found, that information is still sent to the sender of the incoming email. * Make sure dirmngr is killed for a list after refreshing a list's keyring. Avoids servers getting memory exhausted. Fixes #289 * Fixed the API-daemon's interpretation of listnames that start with a number (previously the listname "1list" caused errors because it was taken as the integer 1). ## [3.2.1] / 2017-10-24 ### Changed * Explicitly depend on the latest version of ruby-gpgme (2.0.13) to force existing setups to update. This fixes the problem where unusable keys were not identified as such. (Previous versions of ruby-gpgme failed to properly provide the capabilities of a key.) ## [3.2.0] / 2017-10-23 ### Added * Internal footer: to be appended to each email that is sent to a subscribed address. Will not be included in messages to non-subscribed addresses. This change requires a change to the database, don't forget to run `schleuder install` after updating the code. * Optionally use an OS-wide defined keyserver by configuring a blank value for the keyserver. * Added keywords `X-RESEND-UNENCRYPTED` and `X-RESEND-CC-UNENCRYPTED` to enforce outgoing email(s) in cleartext regardless of whether we would find a key for the recipient or not. ### Changed * Public footer: Whitespace is not anymore stripped from the value of public_footer. * The API does not include anymore each key's key-data in response to `/keys.json`. This avoids performance problems with even medium sized keyrings. * The short representation of GnuPG keys became more human-friendly. Besides the fingerprint we now show the email-address of the first UID, the generation-date, and optionally the expiration-date. * Log the full exception when sending a message fails. (Thanks, Lunar!) * When creating a new list, we do not anymore look for a matching key for the admin-address in the list's keyring. We don't want to look up keys for subscriptions by email at all. (This was anyway only useful in the corner case where you prefilled a keyring to use for the new list.) * API: Access to `/status.json` is now allowed without authentication. * Deprecate X-LISTNAME in favour of X-LIST-NAME, for the sake of consistency in spelling keywords (but X-LISTNAME is still supported). (Thanks, maxigas!) ### Fixed * X-SUBSCRIBE now handles the combination of space-separated fingerprint and additional arguments (admin-flag, delivery-enabled-flag) correctly. * Fixed broken encoding of certain character-sequences in encrypted+signed messages. * X-LIST-KEYS again works without arguments. * X-RESEND now checks the given arguments to be valid email-addresses, and blocks resending if any one is found invalid. * X-RESEND now respects the encoding the mail was sent with. (Thanks, Lunar!) ## [3.1.2] / 2017-07-13 ### Changed * Sort lists alphabetically by email per default. ### Fixed * Fix dropping mails on certain headers (e.g. spam), as the headers weren't checked properly so far. * Fix processing of bounced messages. If a bounced messaged contained a PGP message (which most messages sent by schleuder have), schleuder tried to decrypt it before processing as a bounced message. This failed in nearly all cases, leading to double bounces. (#234) * Fix reading messages with empty Content-Type-header. Some automatically sent messages don't have one. * Do not try to fix text/plain messages from outlook (#246) ## [3.1.1] / 2017-06-24 ### Added * New cli-command `pin_keys` to pin the subscriptions of a list to a respective key (#225). Running this fixes the shortcoming of the code for list-migration mentioned below. ### Changed * Allow to run `refresh_keys` only for a given list. ### Fixed * **When migrating a v2-list, lookup keys for subscriptions** and assign the fingerprint if it was a distinct match. Otherwise people that had no fingerprint set before will receive plaintext emails — because in v3 we're not anymore looking up keys for subscriptions by email address. (To fix this for already migrated lists please use `schleuder pin_keys $listname`). * When migrating a v2-list, assign the looked up fingerprint to an admin only if it was a distinct match. * When migrating a v2-list, do not enable delivery for admins that weren't a member. (#213) * When migrating a v2-list, subscribe duplicated members only once (#208) * When migrating a v2-list, properly deal with admins that have no (valid) key. (#207) * When creating a list, only use distinctly found keys for admins. * Skip unusable keys when resending. * Don't report unchanged keys when refreshing keys. * Fix adding the subject-prefix to an empty subject (#226) * Do not detect emails sent from cron-scripts as bounces (#205) * Fix working with multipart/alternative-messages that contain inline OpenPGP-data. We're now stripping the HTML-part to enable properly handling the ciphertext. * Validate that an email address can be subscribed only once per list. * Fixed settings subscription-attributes (admin, delivery_enabled) when suscribing through schleuder-web. * schleuder-api-daemon SysV init script: Fix formatting and styling, add recommend and required commands {status,reload,force-reload} by Lintian. (#230) * Don't require database-adapter early. Helps when using a different database-system than sqlite. * Fix text of admin-notification from plugin-runners. * Avoid loops on notifying list admins (#229) ## [3.1.0] / 2017-05-21 ### Added * `X-GET-LOGFILE`. Sends you the logfile of the list. * `X-ATTACH-LISTKEY`. Attaches the list's key to a message. Useful in combination with `X-RESEND`. * `X-GET-VERSION`. Sends you the version of Schleuder that is running your list. * API-endpoint to trigger sending the list's key to all subscriptions. ### Changed * Don't write errors of list-plugins into the list of pseudo-headers. List-plugins must handle errors on their own. * Allow request-plugins to return attachments. * Fix x-get-key for multiple keys per match, and attach the resulting keys. * Tolerate 0x-prefix on input for fingerprints of subscriptions. * Tolerate spaces on input for fingerprints in keywords. * `X-GET-KEY` returns keys as attachments now. * `X-SIGN-THIS` returns attachments now, too. * The texts that describe the forwarded automated messages now reflect that not all of those were bounces. * Use single SQL-query instead of five, in select-statement in postfix/schleuder_sqlite.cf. * Use sender() to specify the return-address, instead of setting a Return-Path. ### Fixed * Make `public_footer` appear at the bottom of messages, not at the top. * Remove excessive empty lines in output of refresh-keys. * Amended list of dependencies in README. * Fix `X-GET-KEY` for multiple keys per match. * Also report if a key-import didn't change a present key. * Fix bounce-address in postfix/schleuder_sqlite.cf. ## [3.0.4] / 2017-04-15 ### Changed * Harmonize format of key `check` and `update` texts. ### Fixed * Fix unlegible messages (we mis-handled base64-encoded message-parts under some circumstances). * Avoid run-on paragraphs in key `check` and `update` reports (Thanks, dkg!) * Let schleuder-cli request check keys (allow /keys/check_keys.json to be reached). ## [3.0.3] / 2017-02-16 ### Changed * Require fingerprints of lists and subscriptions to be at least 32 characters long. Previously it was possible to assign shorter hexadecimal strings. * Key lookup for arguments to X-keywords is stricter than before: if you supply a string containing an "@", gnupg will be told to only match it against email-addresses; if you send a hexadecimal string, gnupg will be told to only match it against fingerprints. * Fixed and improved X-DELETE-KEY to only allow deletion of a single key, and only if no matching secret key is present. * Fixed and improved X-FETCH-KEY to use the configured keyserver; to handle URLs, fingerprints, and email-addresses alike; and to send internationalized messages. * Go back to make mock SKS-server listen on 127.0.0.1 — the former IP resulted in errors on some systems. ### Fixed * Don't break multipart/alternative-parts when inserting our pseudo-headers. * X-ADD-KEY handles inline content from Thunderbird correctly. * X-SIGN-THIS now looks recursively for attachments to sign. * Fixed unsubscribing oneself with X-UNSUBSCRIBE. * Fixed setting fingerprint for other subscription than oneself with X-SET-FINGERPRINT. * Better output of X-LIST-SUBSCRIPTIONS if no subscriptions are present. * Sensible error message if X-GET-KEY doesn't find a matching key. * Allow '0x'-prefix of fingerprints when given as keyword-argument. * If no keyword generates output, a sensible error message is used. ### Added * More rspec-tests. ## [3.0.2] / 2017-02-01 ### Changed * Use less usual IP and port number for mock SKS-server. Previously this conflicted with actual SKS-servers running on the same machine. ### Added * Call refresh_keys in provided crontab-script. ### Fixed * Fixed importing member-fingerprints when migrating a list. * Fix clearing passphrase during list-migration with GnuPG 2.0.x by actually shipping the required pinentry-script. * Corrected english phrasing and spelling for error message in case of wrong argument to listname-keyword. (Thanks, dkg!) ## [3.0.1] / 2017-01-26 ### Fixed * Fixed setting admin- and delivery-flags on subscription. Requests from schleuder-cli were interpreted wrongly, which led to new lists having no admins. * A short description for the man-page of schleuder-api-daemon to satisfy the lintian. * Listing openssl as dependency in README. If the openssl header-files are not present when eventmachine compiles its native code, schleuder-api-daemon cannot use TLS. * Removed reference to Github from Code of Conduct. ## [3.0.0] / 2017-01-26 ### Changed * **API-keys always required!** From now on all requests to schleuder-api-daemon require API-keys, even via localhost. This helps protecting against rogue non-root-accounts or -scripts on the local machine. * **TLS always used!** schleuder-api-daemon now always uses TLS. * Switched project-site and git-repository to . * Set proper usage flags when creating a new OpenPGP-key: the primary key gets "SC", the subkey "E". (Thanks, dkg!) * Avoid possible future errors by ignoring every unknown output of gpg (like GnuPG's doc/DETAILS recommends). (Thanks, dkg!) * Friendlier error message if delivery to subscription fails. * Set list-email as primary address after adding UIDs. Previously it was a little random, for reasons only known to GnuPG. * Only use temporary files where necessary, and with more secure paths. * Tighten requirements for valid email-addresses a little: The domain-part may now only contain alphanumeric characters, plus these: `._-` * Required version of schleuder-cli: 0.0.2. ### Added * X-LISTNAME: A **new mandatory keyword** to accompany all keywords. From now on every message containing keywords must also include the listname-keyword like this: `X-LISTNAME: list@hostname` The other keywords will only be run if the given listname matches the email-address of the list that the message is sent to. This mitigates replay-attacks among different lists. * Also send helpful message if a subscription's key is present but unusable. * Provide simpler postfix integration, now using virtual_domains and an sql-script. (Thanks, dkg!) * Enable refreshing keys from keyservers: A script that is meant to be run regularly from cron. It refreshes each key of each list one by one from a configurable keyserver, and sends the result to the respective list-admins. * Import attached, ascii-armored keys from messages with `add-key`-keyword. (Thanks, Kéfir!) * Check possible key-material for expected format before importing it. (Thanks, Kéfir!) ### Fixed * Allow fingerprints to be prefixed with '0x' in `subscribe`-keyword. * Also delete directory of list-logfile on deletion if that resides outside of the list-dir. * Sign and possibly encrypt error notifications. * Fix setting admin- and delivery-flags while subscribing. * Fix subscribing from schleuder-cli. * Fix finding subscriptions from signatures made by a signing-capable sub-key. ## [3.0.0.beta17] / 2017-01-12 ### Changed * Stopped using SCHLEUDER_ROOT in specs. Those make life difficult for packaging for debian. * While running specs, ensure smtp-daemon.rb has been stopped before starting it anew. ### Added * A Code of Conduct. ## [3.0.0.beta16] / 2017-01-11 ### Fixed * Fix running `schleuder migrate...`. * Fix assigning list-attributes when migrating a list. ### Added * Import the secret key and clear its passphrase when migrating a list from v2. * More tests. ## [3.0.0.beta15] / 2017-01-10 ### Changed * Default `lists_dir` and `listlogs_dir` to `/var/lib/schleuder`. * Use '/usr/local/bin' as daemon PATH in schleuder-api-daemon sysvinit script. ### Fixed * Fix running for fresh lists if `lists_dir` is different from `listlogs_dir` (by creating logfile-basedir, closes Debian bug #850545). * Fix error-message from ListBuilder if given email is invalid. * Fix checking for sufficient gpg-version (previously '2.1' didn't suffice if '2.1.0' was required). ### Added * Cron job file to check keys. * Show when delivery is disabled for a subscription (in reply to 'list-subscriptions'-keyword). * Add timeout to default sqlite-config (avoids errors in the case that the DB-file is locked on first attempt). * Provide method to call gpg-executable. * Also add additional UIDs to generated PGP-keys when using gpg 2.0. * Specs for ListBuilder. ## [3.0.0.beta14] / 2016-12-29 ### Fixed * Fix key expiry check * Fix link to schleuder.nadir.org in List-Help header * Fix deleting listdir ### Added * Runner and integration tests * More fixtures ## [3.0.0.beta13] / 2016-12-22 ### Fixed * Fix creating new lists. ## [3.0.0.beta12] / 2016-12-22 ### Changed * Show file permission warning if cert is being generated as root. * Use hard-coded defaults as base to merge config-file over. ### Added * New keyword `x-resend-cc` to send a message to multiple recipients that should know of each another. The ciphertext will be encrypted only once to all recipients, too. * More specs. * Skript for schleuder-api-daemon under sysvinit. ### Fixed * Fix tests for non-default listlogs_dir. * Fix pseudo-header "Sig" for unknown keys. * Fix adding subject_prefix_in for unencrypted messages. * Fix checking permissions of listdir and list.log for newly created lists. * Fix occasionally empty 'date'-pseudo-header. ## [3.0.0.beta11] / 2016-12-07 ### Changed * Fixed recognition and validation of clearsigned-inline messages. * Fix log-file rotation (for list.log). * Show hint to set `use_tls: true` after generation of certificate. ### Added * During installation, show error message and exit if data of an installation of schleuder-2.x is found in the configured lists_dir. * More tests. ## [3.0.0.beta10] / 2016-12-05 ### Changed * Fixed tarball to contain correct version and state of changelog. ## [3.0.0.beta9] / 2016-12-02 ### Added * Include tarball into release. * Make basedir of list-logs configurable (`listlogs_dir`). No operational change with the default value. * Recognize "encapsulated" signatures (RFC 3156, 6.1). (These signatures might still be reported as invalid, that's a bug in mail-gpg which will probably be fixed in their next release.) * Make installed schleuder-files accessible for owner and group only. * Make list-logs accessible to owner and group only. ### Changed * Improved documentation. ### Fixed * Fix checking for empty messages for nested multiparts (e.g. Thunderbird with memoryhole-headers). * Fix `schleuder install` to respect config settings (e.g. `lists_dir`) ## [3.0.0.beta8] / 2016-11-27 ### Changed * Add network and local-filesystem as dependencies in systemd-unit-file. * Improved documentation. ### Fixed * Declare dependency on thin. ## [3.0.0.beta7] / 2016-11-23 ### Added * `man`-page for schleuder(8). * schleuder-api-daemon: optionally use TLS. * schleuder-api-daemon: authenticate client by API-key if TLS is used. ### Changed * Sign git-tags, gems, and tarballs as 0xB3D190D5235C74E1907EACFE898F2C91E2E6E1F3. * Rename schleuderd to schleuder-api-daemon. * schleuder-api-daemon: bind to `localhost` by default. * schleuder-api-daemon: changed name of `bind` config option to `host`. * schleuder-api-daemon: return 204 if not content is being sent along. * Refactor and improve model validations. ### Fixed * Fixed creating lists. * Fixed default config. * Log errors to syslog-logger in case of problems with list-dir. ## [3.0.0.beta6] / 2016-11-13 ### Added * Add `-v`, `--version` arguments to CLI. * New model validators. * Translations (de, en) and better wording for validation error messages. * Specs (test-cases) for the list model. * Use Travis to automate testing. * Test listname to be a valid email address before creating list. * A simple contribution guide. * Check that GnuPG >= 2.0 is being used. * Enable to specify path to gpg-executable in GPGBIN environment variable. * A simple schleuder-only MTA to help with development. ### Changed * schleuderd: use GET instead of OPTIONS to work around bug in ruby 2.1. * Allow "inline"-pgp for request-messages (mail-gpg 0.2.7 fixed their issue). ### Fixed * Fix testing nested messages for emptiness. * Fix bouncing a message if it was found to be empty. * Fix truncated 'adding UID failed' message (transported via HTTP-headers). ## ... --------- The format of this file is based on [Keep a Changelog](http://keepachangelog.com/). Template, please ignore: ## [x.x.x] / YYYY-MM-DD ### Added ### Changed ### Deprecated ### Removed ### Fixed ### Security schleuder-3.6.0/CODE_OF_CONDUCT.md000066400000000000000000000044031401002544500162710ustar00rootroot00000000000000# Schleuder's Code of Conduct The Schleuder development team wants to provide an open and welcoming environment for everyone who participates in the development of Schleuder regardless of level of experience, gender, gender identity and expression, sexual orientation, disability, physical appearance, race, ethnicity, economic or social status, age, religion, or nationality. Harassment in code and discussion or violation of physical boundaries is completely unacceptable anywhere in the Schleuder project. We welcome contributions from everyone that adheres to these principles. Violators will be warned, blocked or banned by the development team. ### In detail Harassment includes offensive verbal comments related to level of experience, gender, gender identity and expression, sexual orientation, disability, physical appearance, body size, race, ethnicity, age, religion, nationality, the use of sexualized language or imagery, deliberate intimidation, stalking, sustained disruption, and unwelcome sexual attention. Individuals asked to stop any harassing behavior are expected to comply immediately. Maintainers, including the development team, are also subject to the anti-harassment policy. If anyone engages in abusive, harassing, or otherwise unacceptable behavior, including maintainers, we will take appropriate action, up to and including warning the offender, deletion of comments, removal from the project’s codebase and communication systems. If you are being harassed, notice that someone else is being harassed, or have any other concerns, please [contact the development team](https://schleuder.org/contact.html) immediately. We expect everyone to follow these rules anywhere in the Schleuder project’s codebases, issue trackers, IRC channel, group chat, mailing lists, meetups, and any other events. This code of conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Finally, don't forget that it is human to make mistakes! We all do. Let’s work together to help each other, resolve issues, and learn from the mistakes that we will all inevitably make from time to time. ### Thanks Thanks to the [Bundler Code of Conduct](https://bundler.io/conduct.html), which we adopted for ourselves. schleuder-3.6.0/CONTRIBUTING.md000066400000000000000000000077021401002544500157300ustar00rootroot00000000000000Contributing ============ To contribute please follow this workflow: 1. Talk to us! E.g. create an issue about your idea or problem. 2. Fork the repository and work in a meaningful named branch that is based off of our "master". 3. Enable CI: In your fork, go to Settings -> CI / CD -> Expand next to Runners settings -> Enable shared Runners. 4. Commit in rather small chunks but don't split depending code across commits. Please write sensible commit messages. 5. Please add tests for your feature or bugfix. 6. If in doubt request feedback from us! 7. When finished create a merge request. Thank you for your interest! ## Tutorial: Getting started with schleuder development This short beginner's guide helps you getting started in schleuder development. ### Set up environment First, we have to set up the development environment. We use [rvm](https://rvm.io/rvm/basics) to avoid dependency version mixups with other ruby projects. 1. Install ruby and [rvm](https://rvm.io/rvm/basics). 2. Clone the schleuder repository and cd into it. 3. Create a rvm gemset: ``` rvm gemset create schleuder rvm gemset use schleuder rvm gemset list # checks if it uses the correct gemset ``` 4. Install bundler: `gem install bundler` 5. Install dependencies with bundler: ``` bundle install ``` ### Getting started with development To start with the actual development, we first have to get the schleuder system running. 1. Install schleuder: `rvmsudo bin/schleuder install` 2. Set permissions: ``` sudo chown -R /var/lib/schleuder/ sudo chown -R /etc/schleuder/ ``` 3. Clone and install schleuder-cli: ``` wget https://0xacab.org/schleuder/schleuder-cli/raw/master/gems/schleuder-cli-0.1.0.gem.sig && gpg --verify schleuder-cli-0.1.0.gem.sig gem install schleuder-cli-0.1.0.gem ``` 4. Configure schleuder-cli: ``` schleuder cert fingerprint | cut -d ' ' -f 4 # copy the output to tls_fingerprint in ~/.schleuder-cli/schleuder-cli.yml schleuder new_api_key # copy the output to api_key in ~/.schleuder-cli/schleuder-cli.yml AND /etc/schleuder/schleuder.yml ``` 5. Start schleuder-api-daemon: `schleuder-api-daemon` 6. Test if everything works by running (should not return an error): `schleuder-cli lists list` #### Manual testing and debugging After we have implemented our code, it is time to test and debug it. To do that manually, we create a test list via schleuder-cli and throw in test emails. There is a mock smtp daemon in `bin/schleuder-smtpd.rb` to help us test without a fully configured mail server. This short tutorial will help you initialize the manual debug setup. 0. Create a list with a test public key: ``` gpg --export --armor > pubkey.gpg schleuder-cli lists new test@test pubkey.gpg ``` 1. Start fake smtp daemon: `rvmsudo ruby bin/schleuder-smtpd.rb`. Throw a test mail into it to verify it is running: ``` echo "test" | mailx -s "test" -S smtp=smtp://localhost list@list ``` 2. Create an email to send and store it in a file (e.g. `mail.txt`): ``` To: test@test From: root@localhost Subject: Test Test ``` 3. Throw email in `cat mail.txt | schleuder work test@test`. The receivers of the mail can be seen in the output of `schleuder-smtpd.rb` 4. Start debugging your code! From that we additionally can use schleuder-cli to set the list options or create different test scenarios. Remember to restart the `schleuder-api-daemon` if you make any changes to the list config options. #### Changing the database - To change the database add a file to `db/migrate/` that has the same structure as the files in there. Then call `rake db:migrate`. - To downgrade a specific change use: `rake db:migrate:down VERSION=` - To upgrade a specific change use: `rake db:migrate:up VERSION=` #### Automated tests - Automated tests are defined in `spec/` - Execute automated tests: ``` SCHLEUDER_ENV=test SCHLEUDER_CONFIG=spec/schleuder.yml bundle exec rake db:init bundle exec rspec ``` schleuder-3.6.0/Gemfile000066400000000000000000000001371401002544500147650ustar00rootroot00000000000000source 'https://rubygems.org' # Specify your gem's dependencies in schleuder.gemspec gemspec schleuder-3.6.0/LICENSE.txt000066400000000000000000001045131401002544500153200ustar00rootroot00000000000000 GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS 0. Definitions. "This License" refers to version 3 of the GNU General Public License. "Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. "The Program" refers to any copyrightable work licensed under this License. Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals or organizations. To "modify" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a "modified version" of the earlier work or a work "based on" the earlier work. A "covered work" means either the unmodified Program or a work based on the Program. To "propagate" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. To "convey" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. An interactive user interface displays "Appropriate Legal Notices" to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. 1. Source Code. The "source code" for a work means the preferred form of the work for making modifications to it. "Object code" means any non-source form of a work. A "Standard Interface" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. The "System Libraries" of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A "Major Component", in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. The "Corresponding Source" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. The Corresponding Source for a work in source code form is that same work. 2. Basic Permissions. All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. 3. Protecting Users' Legal Rights From Anti-Circumvention Law. No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. 4. Conveying Verbatim Copies. You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. 5. Conveying Modified Source Versions. You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: a) The work must carry prominent notices stating that you modified it, and giving a relevant date. b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to "keep intact all notices". c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an "aggregate" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. 6. Conveying Non-Source Forms. You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. A "User Product" is either (1) a "consumer product", which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, "normally used" refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. "Installation Information" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. 7. Additional Terms. "Additional permissions" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or d) Limiting the use for publicity purposes of names of licensors or authors of the material; or e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. All other non-permissive additional terms are considered "further restrictions" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. 8. Termination. You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. 9. Acceptance Not Required for Having Copies. You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. 10. Automatic Licensing of Downstream Recipients. Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. An "entity transaction" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. 11. Patents. A "contributor" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's "contributor version". A contributor's "essential patent claims" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, "control" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. In the following three paragraphs, a "patent license" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To "grant" such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. "Knowingly relying" means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. A patent license is "discriminatory" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. 12. No Surrender of Others' Freedom. If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. 13. Use with the GNU Affero General Public License. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. 14. Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. 15. Disclaimer of Warranty. THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 17. Interpretation of Sections 15 and 16. If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . Also add information on how to contact you by electronic and paper mail. If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: Copyright (C) This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, your program's commands might be different; for a GUI interface, you would use an "about box". You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see . The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . schleuder-3.6.0/MISSION_STATEMENT.md000066400000000000000000000014361401002544500165640ustar00rootroot00000000000000# Schleuder's Mission Statement We give our time and knowledge to build and maintain this project in order to help people with their daily private communication and in the struggle for their personal emancipation, social and economic justice and political freedom. A more human world, in which anyone can be different without fear, is what we strive for. We work transparently and responsibly, and don't collaborate with surveillance actors. We do not endorse any form of authoritarian movement or totalitarian system, and wish for that Schleuder may not ever be used to promote or enable them. Instead we are committed to ideas and principles outlined in our [Code of Conduct](https://0xacab.org/schleuder/schleuder/blob/master/CODE_OF_CONDUCT.md). If you do not agree, do not use Schleuder. schleuder-3.6.0/README.md000066400000000000000000000113411401002544500147500ustar00rootroot00000000000000Schleuder, version 3 ====================================== Schleuder is a gpg-enabled mailing list manager with resending-capabilities. Subscribers can communicate encrypted (and pseudonymously) among themselves, receive emails from non-subscribers and send emails to non-subscribers via the list. Version 3 of schleuder is a complete rewrite, which aims to be more robust, flexible, and internationalized. It also provides an API for the optional web interface called [schleuder-web](https://0xacab.org/schleuder/schleuder-web). For more details see . Requirements ------------ * ruby >=2.1 * gnupg 2.0.x, or >=2.1.16 * gpgme * sqlite3 * openssl * icu *If you use Debian buster or CentOS 7, please have a look at the [installation docs](https://schleuder.org/schleuder/docs/server-admins.html#installation). We do provide packages for those platforms, which simplify the installation a lot.* *🛈 A note regarding Ubuntu: All Ubuntu versions up to and including 17.10 don't meet the requirements with their packaged versions of gnupg! To run Schleuder on Ubuntu you currently have to install a more recent version of gnupg manually. Only Ubuntu 18.04 ("bionic") provides modern enough versions of Schleuder's requirements.* On systems that base on Debian 10 ("buster"), install the dependencies via apt-get install ruby-dev gnupg2 libgpgme-dev libsqlite3-dev libssl-dev build-essential libicu-dev We **recommend** to also run a random number generator like [haveged](http://www.issihosts.com/haveged/). This ensures Schleuder won't be blocked by lacking entropy, which otherwise might happen especially during key generation. On Debian based systems, install it via apt-get install haveged Additionally these **rubygems** are required (will be installed automatically unless present): * rake * active_record * sqlite3 * thor * thin * mail-gpg * sinatra * sinatra-contrib Installing Schleuder ------------ 1. Download [the gem](https://schleuder.org/download/schleuder-3.6.0.gem) and [the OpenPGP-signature](https://schleuder.org/download/schleuder-3.6.0.gem.sig) and verify: ``` gpg --recv-key 0xB3D190D5235C74E1907EACFE898F2C91E2E6E1F3 gpg --verify schleuder-3.6.0.gem.sig ``` 2. If all went well install the gem: ``` gem install schleuder-3.6.0.gem ``` 3. Set up schleuder: ``` schleuder install ``` This creates necessary directories, copies example configs, etc. If you see errors about missing write permissions please follow the advice given. For further information on setup and configuration please read . Command line usage ----------------- See `schleuder help`. E.g.: Commands: schleuder check_keys # Check all lists for unusable or expiring keys and send the results to the list-admins. (This is supposed... schleuder help [COMMAND] # Describe available commands or one specific command schleuder install # Set up Schleuder initially. Create folders, copy files, fill the database, etc. schleuder version # Show version of schleuder schleuder work list@hostname < message # Run a message through a list. List administration ------------------- Please use [schleuder-cli](https://0xacab.org/schleuder/schleuder-cli) to create and manage lists from the command line. Optionally consider installing [schleuder-web](https://0xacab.org/schleuder/schleuder-web), the web interface for schleuder. It enables list-admins to manage their lists through the web instead of using [request-keywords](https://schleuder.org/docs/#subscription-and-key-management). Todo ---- See . Testing ------- We use rspec to test our code. To setup the test environment run: SCHLEUDER_ENV=test SCHLEUDER_CONFIG=spec/schleuder.yml bundle exec rake db:init To execute the test suite run: bundle exec rspec Please note: Some of the specs use 'pgrep'. On systems that base on Debian 10 ("buster") install it via apt-get install procps We are working on extendig the test coverage. Contributing ------------ Please see [CONTRIBUTING.md](CONTRIBUTING.md). Mission statement ----------------- Please see [MISSION_STATEMENT.md](MISSION_STATEMENT.md). Code of Conduct --------------- We adopted a code of conduct. Please read [CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md). License ------- GNU GPL 3.0. Please see [LICENSE.txt](LICENSE.txt). Alternative Download -------------------- Alternatively to the gem-files you can download the latest release as [a tarball](https://schleuder.org/download/schleuder-3.6.0.tar.gz) and [its OpenPGP-signature](https://schleuder.org/download/schleuder-3.6.0.tar.gz.sig). schleuder-3.6.0/Rakefile000066400000000000000000000066361401002544500151510ustar00rootroot00000000000000project = 'schleuder' require_relative "lib/#{project}.rb" @version = Schleuder::VERSION @tagname = "#{project}-#{@version}" @gpguid = 'B3D190D5235C74E1907EACFE898F2C91E2E6E1F3' @filename_gem = "#{@tagname}.gem" @filename_tarball = "#{@tagname}.tar.gz" load "active_record/railties/databases.rake" # Configure ActiveRecord ActiveRecord::Tasks::DatabaseTasks.tap do |config| config.root = File.dirname(__FILE__) config.db_dir = 'db' config.migrations_paths = ['db/migrate'] config.env = ENV['SCHLEUDER_ENV'] config.database_configuration = Schleuder::Conf.databases end # ActiveRecord requires this task to be present Rake::Task.define_task("db:environment") namespace :db do # A shortcut. task init: ['db:create', 'db:schema:load'] end def edit_and_add_file(filename) puts "Please edit #{filename} to refer to version #{@version}" if system("gvim -f #{filename}.md") `git add #{filename}.md` else exit 1 end end task :console do exec "irb -r #{File.dirname(__FILE__)}/lib/schleuder.rb" end task :publish_gem => :website task :git_tag => :check_version desc "Build new version: git-tag and gem-file" task :new_version => [ :check_version, :edit_readme, :edit_changelog, :git_add_version, :git_commit, :build_gem, :sign_gem, :build_tarball, :sign_tarball, :ensure_permissions, :git_tag ] do end desc "Edit CHANGELOG.md" task :edit_changelog do edit_and_add_file('CHANGELOG') end desc "Edit README" task :edit_readme do edit_and_add_file('README') end desc 'git-tag HEAD as new version' task :git_tag do `git tag -u #{@gpguid} -s -m "Version #{@version}" #{@tagname}` end desc "Add changed version to git-index" task :git_add_version do `git add lib/#{project}/version.rb` end desc "Commit changes as new version" task :git_commit do `git commit -m "Version #{@version}"` end desc 'Build, sign and commit a gem-file.' task :build_gem do `gem build #{project}.gemspec` end desc 'OpenPGP-sign gem and tarball' task :sign_tarball do `gpg -u #{@gpguid} -b #{@filename_tarball}` end desc 'OpenPGP-sign gem' task :sign_gem do `gpg -u #{@gpguid} -b #{@filename_gem}` end desc 'Ensure download-files have correct permissions' task :ensure_permissions do File.chmod(0644, *Dir.glob("#{@tagname}*")) end desc 'Upload download-files (gem, tarball, signatures) to schleuder.org.' task :upload_files do puts `echo "put -p #{@tagname}* www/download/" | sftp schleuder.org@ftp.schleuder.org 2>&1` end desc 'Publish gem-file to rubygems.org' task :publish_gem do puts "Really push #{@filename_gem} to rubygems.org? [yN]" if $stdin.gets.match(/^y/i) puts "Pushing..." `gem push #{@filename_gem}` else puts "Not pushed." end end desc 'Build and sign a tarball' task :build_tarball do `git archive --format tar.gz --prefix "#{@tagname}/" -o #{@filename_tarball} master` end desc 'Describe manual release-tasks' task :website do puts "Please remember to publish the release-notes on the website and on schleuder-announce." end desc 'Check if version-tag already exists' task :check_version do # Check if Schleuder::VERSION has been updated since last release if `git tag`.match?(/^#{@tagname}$/) $stderr.puts "Warning: Tag '#{@tagname}' already exists. Did you forget to update lib/#{project}/version.rb?" $stderr.print "Delete tag to continue? [yN] " if $stdin.gets.match(/^y/i) `git tag -d #{@tagname}` else exit 1 end end end schleuder-3.6.0/bin/000077500000000000000000000000001401002544500142415ustar00rootroot00000000000000schleuder-3.6.0/bin/pinentry-clearpassphrase000077500000000000000000000025201401002544500212140ustar00rootroot00000000000000#!/usr/bin/env ruby # This file can be deleted once we cease to support gnupg 2.0. require 'fileutils' require 'cgi' require 'openssl' def respond(msg, flush=true) $stdout.puts msg if flush $stdout.flush end end def send_ok(flush=true) respond 'OK', flush end def send_password if File.exist?(OLDPWDSENTFILE) pwd = '' if File.exist?(EMPTYPWDSENTFILE1) FileUtils.touch(EMPTYPWDSENTFILE2) else FileUtils.touch(EMPTYPWDSENTFILE1) end else pwd = OLDPASSWD FileUtils.touch(OLDPWDSENTFILE) end respond "D #{pwd}" end def do_exit if File.exist?(EMPTYPWDSENTFILE2) FileUtils.rm_rf(TMPDIR) end exit 0 end OLDPASSWD = CGI.escape(ENV['PINENTRY_USER_DATA'].to_s) if OLDPASSWD.empty? respond "Fatal error: passed PINENTRY_USER_DATA was empty, cannot continue" exit 1 end # We need a static directory name to maintain the state across invocations of # this file. TMPDIR = File.join(ENV['GNUPGHOME'], '.tmp-pinentry-clearpassphrase') OLDPWDSENTFILE = File.join(TMPDIR, '1') EMPTYPWDSENTFILE1 = File.join(TMPDIR, '2') EMPTYPWDSENTFILE2 = File.join(TMPDIR, '3') if ! Dir.exist?(TMPDIR) Dir.mkdir(TMPDIR) end respond "OK - what's up?" while line = $stdin.gets do case line when /^GETPIN/ send_password send_ok when /^BYE/ send_ok false do_exit else send_ok end end schleuder-3.6.0/bin/schleuder000077500000000000000000000005531401002544500161500ustar00rootroot00000000000000#!/usr/bin/env ruby # Don't emit any warnings, they would be sent back to the email-sender as an # error-message. $VERBOSE=nil trap("INT") { exit 1 } begin $LOAD_PATH.unshift(File.expand_path('../../lib', __FILE__)) require 'schleuder/cli' Schleuder::Cli.start rescue => exc $stderr.puts "Technical Error: #{exc}\n#{exc.backtrace.first}" exit 1 end schleuder-3.6.0/bin/schleuder-api-daemon000077500000000000000000000002101401002544500201460ustar00rootroot00000000000000#!/usr/bin/env ruby $LOAD_PATH.unshift(File.expand_path('../../lib', __FILE__)) require 'schleuder-api-daemon' SchleuderApiDaemon.run! schleuder-3.6.0/bin/schleuder-bundler000077500000000000000000000003631401002544500176000ustar00rootroot00000000000000#!/bin/bash -l export HOME=/home/$(id -nu) # Little helper script to call schleuder through bundler. Useful e.g. for # hooking up development code into postfix. bindir="$(realpath $(dirname $0))" cd $bindir/.. bundle exec ./bin/schleuder $@ schleuder-3.6.0/bin/schleuder-smtpd.rb000077500000000000000000000032761401002544500177040ustar00rootroot00000000000000#!/usr/bin/env ruby # # This script is a very simple SMTP-daemon, that delivers every incoming email # to a given schleuder-list. It's meant to help developing without a real, # local MTA. require 'socket' require 'open3' trap ("INT") { exit 0 } def usage puts "Usage: #{File.basename(__FILE__)} [-p portnum]" exit 1 end # get args case ARGV.first when '-h', '--help', 'help' usage when '-p' port = ARGV[1].to_i if port == 0 usage end end port ||= 25 schleuderbin = File.join(File.dirname(__FILE__), 'schleuder') begin # run the server server = TCPServer.new("127.0.0.1", port) # receive input while (connection = server.accept) input = '' recipient = '' connection.puts "220 localhost SMTP" begin while line = connection.gets line.chomp! case line[0..3].downcase when 'ehlo', 'helo' connection.puts "250 localhost" when 'mail', 'rset' connection.puts "250 ok" when 'rcpt' recipient = line.split(':').last.gsub(/[<>\s]*/, '') connection.puts "250 ok" when 'data' connection.puts "354 go ahead" when 'quit' connection.puts "221 localhost" when '.' puts "New message to #{recipient}" err, status = Open3.capture2e("#{schleuderbin} work #{recipient}", {stdin_data: input}) if status.exitstatus > 0 puts "Error from schleuder: #{err}." connection.puts "550 #{err}" else connection.puts "250 ok" end else input << line + "\n" end end rescue IOError end connection.close end rescue => exc $stderr.puts exc exit 1 end schleuder-3.6.0/db/000077500000000000000000000000001401002544500140565ustar00rootroot00000000000000schleuder-3.6.0/db/migrate/000077500000000000000000000000001401002544500155065ustar00rootroot00000000000000schleuder-3.6.0/db/migrate/20140501103532_create_lists.rb000066400000000000000000000031701401002544500221470ustar00rootroot00000000000000class CreateLists < ActiveRecord::Migration def up if ! table_exists?(:lists) create_table :lists do |t| t.timestamps t.string :email t.string :fingerprint t.string :gpg_passphrase t.string :log_level, default: 'warn' t.string :default_mime, default: 'mime' t.string :subject_prefix, default: '' t.string :subject_prefix_in, default: '' t.string :subject_prefix_out, default: '' t.string :openpgp_header_preference, default: 'signencrypt' t.text :public_footer, default: '' t.text :headers_to_meta, default: '["from","to","date",":cc"]' t.text :bounces_drop_on_headers, default: '{"x-spam-flag":"yes"}' t.text :keywords_admin_only, default: '["unsubscribe", "unsubscribe", "delete-key"]' t.text :keywords_admin_notify, default: '["add-key"]' t.boolean :send_encrypted_only, default: false t.boolean :receive_encrypted_only, default: false t.boolean :receive_signed_only, default: false t.boolean :receive_authenticated_only, default: false t.boolean :receive_from_subscribed_emailaddresses_only, default: false t.boolean :receive_admin_only, default: false t.boolean :keep_msgid, default: true t.boolean :bounces_drop_all, default: false t.boolean :bounces_notify_admins, default: true t.boolean :include_list_headers, default: true t.boolean :include_openpgp_header, default: true t.integer :max_message_size_kb, default: 10240 end end def down drop_table(:lists) end end end schleuder-3.6.0/db/migrate/20140501112859_create_subscriptions.rb000066400000000000000000000010131401002544500237260ustar00rootroot00000000000000class CreateSubscriptions < ActiveRecord::Migration def up if ! table_exists?(:subscriptions) create_table :subscriptions do |t| t.integer :list_id t.string :email t.string :fingerprint t.boolean :admin, default: false t.boolean :delivery_disabled, default: false t.timestamps end add_index :subscriptions, :list_id add_index :subscriptions, [:email, :list_id], unique: true end end def down drop_table(:subscriptions) end end schleuder-3.6.0/db/migrate/201508092100_add_language_to_lists.rb000066400000000000000000000003531401002544500236420ustar00rootroot00000000000000class AddLanguageToLists < ActiveRecord::Migration def up if ! column_exists?(:lists, :language) add_column :lists, :language, :string, default: 'en' end end def down remove_column(:lists, :language) end end schleuder-3.6.0/db/migrate/20150812165700_change_keywords_admin_only_defaults.rb000066400000000000000000000004741401002544500267610ustar00rootroot00000000000000class ChangeKeywordsAdminOnlyDefaults < ActiveRecord::Migration def up change_column_default :lists, :keywords_admin_only, "[\"subscribe\", \"unsubscribe\", \"delete-key\"]" end def down change_column_default :lists, :keywords_admin_only, "[\"unsubscribe\", \"unsubscribe\", \"delete-key\"]" end end schleuder-3.6.0/db/migrate/20150813235800_add_forward_all_incoming_to_admins.rb000066400000000000000000000004721401002544500265270ustar00rootroot00000000000000class AddForwardAllIncomingToAdmins < ActiveRecord::Migration def up if ! column_exists?(:lists, :forward_all_incoming_to_admins) add_column :lists, :forward_all_incoming_to_admins, :boolean, default: false end end def down remove_column(:lists, :forward_all_incoming_to_admins) end end schleuder-3.6.0/db/migrate/201508141727_change_send_encrypted_only_default.rb000066400000000000000000000003361401002544500264220ustar00rootroot00000000000000class ChangeSendEncryptedOnlyDefault < ActiveRecord::Migration def up change_column_default :lists, :send_encrypted_only, true end def down change_column_default :lists, :send_encrypted_only, false end end schleuder-3.6.0/db/migrate/201508222143_add_logfiles_to_keep_to_lists.rb000066400000000000000000000004071401002544500253730ustar00rootroot00000000000000class AddLogfilesToKeepToLists < ActiveRecord::Migration def up if ! column_exists?(:lists, :logfiles_to_keep) add_column :lists, :logfiles_to_keep, :integer, default: 2 end end def down remove_column(:lists, :logfiles_to_keep) end end 201508261723_rename_delivery_disabled_to_delivery_enabled_and_change_default.rb000066400000000000000000000007321401002544500341750ustar00rootroot00000000000000schleuder-3.6.0/db/migrateclass RenameDeliveryDisabledToDeliveryEnabledAndChangeDefault < ActiveRecord::Migration def up if column_exists?(:subscriptions, :delivery_disabled) rename_column :subscriptions, :delivery_disabled, :delivery_enabled change_column_default :subscriptions, :delivery_enabled, true end end def down rename_column :subscriptions, :delivery_enabled, :delivery_disabled change_column_default :subscriptions, :delivery_disabled, false end end schleuder-3.6.0/db/migrate/201508261815_strip_gpg_passphrase.rb000066400000000000000000000003531401002544500235710ustar00rootroot00000000000000class StripGpgPassphrase < ActiveRecord::Migration def up if column_exists?(:lists, :gpg_passphrase) remove_column :lists, :gpg_passphrase end end def down add_column :lists, :gpg_passphrase, :string end end schleuder-3.6.0/db/migrate/201508261827_remove_default_mime.rb000066400000000000000000000002761401002544500233610ustar00rootroot00000000000000class RemoveDefaultMime < ActiveRecord::Migration def up remove_column :lists, :default_mime end def down add_column :lists, :default_mime, :string, default: 'mime' end end schleuder-3.6.0/db/migrate/20160501172700_fix_headers_to_meta_defaults.rb000066400000000000000000000002611401002544500253510ustar00rootroot00000000000000class FixHeadersToMetaDefaults < ActiveRecord::Migration def up change_column_default :lists, :headers_to_meta, '["from", "to", "date", "cc"]' end def down end end schleuder-3.6.0/db/migrate/20170713215059_add_internal_footer_to_list.rb000066400000000000000000000004011401002544500252370ustar00rootroot00000000000000class AddInternalFooterToList < ActiveRecord::Migration def up if ! column_exists?(:lists, :internal_footer) add_column :lists, :internal_footer, :text, default: '' end end def down remove_column(:lists, :internal_footer) end end schleuder-3.6.0/db/migrate/20180110203100_add_sig_enc_to_headers_to_meta_defaults.rb000066400000000000000000000017351401002544500274760ustar00rootroot00000000000000class AddSigEncToHeadersToMetaDefaults < ActiveRecord::Migration def up change_column_default :lists, :headers_to_meta, '["from", "to", "cc", "date", "sig", "enc"]' list_klass = create_list_klass list_klass.reset_column_information list_klass.find_each do |list| if (list.headers_to_meta & ['sig', 'enc']).empty? list.update(headers_to_meta: list.headers_to_meta + ['sig', 'enc']) end end end def down change_column_default :lists, :headers_to_meta, '["from", "to", "cc", "date"]' list_klass = create_list_klass list_klass.reset_column_information list_klass.find_each do |list| list.update(headers_to_meta: list.headers_to_meta - ['enc','sig']) end end def create_list_klass # Use a temporary class-definition to be independent of the # complexities of the actual class. Class.new(ActiveRecord::Base) do self.table_name = 'lists' self.serialize :headers_to_meta, JSON end end end schleuder-3.6.0/db/migrate/20180723173900_add_deliver_selfsent_to_list.rb000066400000000000000000000004121401002544500254040ustar00rootroot00000000000000class AddDeliverSelfsentToList < ActiveRecord::Migration def up if ! column_exists?(:lists, :deliver_selfsent) add_column :lists, :deliver_selfsent, :boolean, default: true end end def down remove_column(:lists, :deliver_selfsent) end end schleuder-3.6.0/db/migrate/20190906194820_add_autocrypt_header_to_list.rb000066400000000000000000000004421401002544500254240ustar00rootroot00000000000000class AddAutocryptHeaderToList < ActiveRecord::Migration def up if ! column_exists?(:lists, :include_autocrypt_header) add_column :lists, :include_autocrypt_header, :boolean, default: true end end def down remove_column(:lists, :include_autocrypt_header) end end schleuder-3.6.0/db/migrate/20200118170110_add_set_reply_to_to_sender_and_munge_from.rb000066400000000000000000000007011401002544500301020ustar00rootroot00000000000000class AddSetReplyToToSenderAndMungeFrom < ActiveRecord::Migration def up if ! column_exists?(:lists, :set_reply_to_to_sender) add_column :lists, :set_reply_to_to_sender, :boolean, default: false end if ! column_exists?(:lists, :munge_from) add_column :lists, :munge_from, :boolean, default: false end end def down remove_column(:lists, :set_reply_to_to_sender) remove_column(:lists, :munge_from) end end schleuder-3.6.0/db/schema.rb000066400000000000000000000104501401002544500156430ustar00rootroot00000000000000# encoding: UTF-8 # This file is auto-generated from the current state of the database. Instead # of editing this file, please use the migrations feature of Active Record to # incrementally modify your database, and then regenerate this schema definition. # # Note that this schema.rb definition is the authoritative source for your # database schema. If you need to create the application database on another # system, you should be using db:schema:load, not running all the migrations # from scratch. The latter is a flawed and unsustainable approach (the more migrations # you'll amass, the slower it'll run and the greater likelihood for issues). # # It's strongly recommended that you check this file into your version control system. ActiveRecord::Schema.define(version: 20200118170110) do create_table "lists", force: :cascade do |t| t.datetime "created_at" t.datetime "updated_at" t.string "email", limit: 255 t.string "fingerprint", limit: 255 t.string "log_level", limit: 255, default: "warn" t.string "subject_prefix", limit: 255, default: "" t.string "subject_prefix_in", limit: 255, default: "" t.string "subject_prefix_out", limit: 255, default: "" t.string "openpgp_header_preference", limit: 255, default: "signencrypt" t.text "public_footer", default: "" t.text "headers_to_meta", default: "[\"from\", \"to\", \"cc\", \"date\", \"sig\", \"enc\"]" t.text "bounces_drop_on_headers", default: "{\"x-spam-flag\":\"yes\"}" t.text "keywords_admin_only", default: "[\"subscribe\", \"unsubscribe\", \"delete-key\"]" t.text "keywords_admin_notify", default: "[\"add-key\"]" t.boolean "send_encrypted_only", default: true t.boolean "receive_encrypted_only", default: false t.boolean "receive_signed_only", default: false t.boolean "receive_authenticated_only", default: false t.boolean "receive_from_subscribed_emailaddresses_only", default: false t.boolean "receive_admin_only", default: false t.boolean "keep_msgid", default: true t.boolean "bounces_drop_all", default: false t.boolean "bounces_notify_admins", default: true t.boolean "deliver_selfsent", default: true t.boolean "include_list_headers", default: true t.boolean "include_openpgp_header", default: true t.integer "max_message_size_kb", default: 10240 t.string "language", limit: 255, default: "en" t.boolean "forward_all_incoming_to_admins", default: false t.integer "logfiles_to_keep", default: 2 t.text "internal_footer", default: "" t.boolean "include_autocrypt_header", default: true t.boolean "set_reply_to_to_sender", default: false t.boolean "munge_from", default: false end create_table "subscriptions", force: :cascade do |t| t.integer "list_id" t.string "email", limit: 255 t.string "fingerprint", limit: 255 t.boolean "admin", default: false t.boolean "delivery_enabled", default: true t.datetime "created_at" t.datetime "updated_at" end add_index "subscriptions", ["email", "list_id"], name: "index_subscriptions_on_email_and_list_id", unique: true add_index "subscriptions", ["list_id"], name: "index_subscriptions_on_list_id" end schleuder-3.6.0/etc/000077500000000000000000000000001401002544500142445ustar00rootroot00000000000000schleuder-3.6.0/etc/init.d/000077500000000000000000000000001401002544500154315ustar00rootroot00000000000000schleuder-3.6.0/etc/init.d/schleuder-api-daemon000077500000000000000000000042721401002544500213520ustar00rootroot00000000000000#!/bin/sh ### BEGIN INIT INFO # Provides: schleuder-api-daemon # Required-Start: $local_fs $remote_fs $network $syslog # Required-Stop: $local_fs $remote_fs $network $syslog # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: Schleuder API daemon # Description: Schleuder API daemon — provides access for schleuder-cli and schleuder-web ### END INIT INFO PATH=/sbin:/usr/sbin:/bin:/usr/bin . /lib/init/vars.sh . /lib/lsb/init-functions NAME=schleuder-api-daemon DAEMON=/usr/local/bin/schleuder-api-daemon DESC="Schleuder API daemon" PIDFILE=/var/run/$NAME.pid USER=schleuder GROUP=schleuder test -x $DAEMON || exit 5 start_schleuder_api_daemon() { if [ -f "$PIDFILE" ]; then echo "" log_failure_msg "$DESC is running already, please stop it first" exit 1 fi if ! id $USER >/dev/null 2>&1; then log_failure_msg "User \"$USER\" does not exist" exit 1 fi if ! getent group $GROUP >/dev/null 2>&1; then log_failure_msg "Group \"$GROUP\" does not exist" exit 1 fi start-stop-daemon --chuid "$USER":"$GROUP" --start --pidfile $PIDFILE --make-pidfile --background --startas $DAEMON -- $NAME } stop_schleuder_api_daemon() { if [ -f "$PIDFILE" ]; then start-stop-daemon --stop --retry TERM/10/KILL/5 --pidfile $PIDFILE --quiet --oknodo --pidfile "$PIDFILE" rm -f $PIDFILE fi } status_schleuder_api_daemon() { if [ ! -e $PIDFILE ]; then status_of_proc "${DAEMON}" "${DESC}" else status_of_proc -p "${PIDFILE}" "${DAEMON}" "${DESC}" fi } case "$1" in start) log_begin_msg "Starting $DESC" start_schleuder_api_daemon log_end_msg $? ;; stop) log_begin_msg "Stopping $DESC" stop_schleuder_api_daemon log_end_msg $? ;; status) status_schleuder_api_daemon ;; restart|reload|force-reload) log_begin_msg "Restarting $DESC" stop_schleuder_api_daemon start_schleuder_api_daemon log_end_msg $? ;; *) echo "Usage: $0 {start|stop|status|restart|reload|force-reload}" exit 1 ;; esac schleuder-3.6.0/etc/list-defaults.yml000066400000000000000000000125731401002544500175570ustar00rootroot00000000000000# Setting default values for newly generated lists. Once a list is created it # is not affected by these settings but has its own set of options in the # database. # # The configuration format is yaml (http://www.yaml.org). # # Options are listed with the behaviour encoded in the database schema. # Only send out encrypted emails to subscriptions? # (This setting does not affect resend-messages.) send_encrypted_only: true # Allow only encrypted emails? If true, any other email will be bounced. receive_encrypted_only: false # Allow only emails that are validly signed? If true, any other email will be # bounced. receive_signed_only: false # Allow only emails that are validly signed by a subscriber's key? If true, # any other email will be bounced. receive_authenticated_only: false # Allow only emails being sent from subscribed addresses? If true, any other # email will be bounced. # NOTE: This is a very weak restriction mechanism on which you should not rely, # as sending addresses can easily be faked! We recommend you to rather # rely on the `receive_authenticated_only` option. Setting the # `receive_authenticated_only` option to true, will authenticate senders # based on the signature on the mail, which is the strongest # authentication mechanism you can get. # This option could be useful, if you would like to have a closed # mailinglist, but could not yet get all subscribers to properly use GPG. receive_from_subscribed_emailaddresses_only: false # Allow only emails that are validly signed by a list-admin's key. # This is useful for newsletters, announce or notification lists receive_admin_only: false # Which headers to include from the original mail. headers_to_meta: - from - to - cc - date - sig - enc # Preserve the Message-IDs (In-Reply-To, References) from the incoming email. # This setting can lead to information leakage, as replies are connectable # and a thread of (encrypted) messages can be built by an eavesdropper. keep_msgid: true # Which keywords ("email-commands") should be restricted to list-admins? keywords_admin_only: - subscribe - unsubscribe - delete-key # For which keywords should the list-admins receive a notice whenever it # triggers a command. keywords_admin_notify: - add-key # Footer to append to each email that is sent to a subscribed address. Will not # be included in messages to non-subscribed addresses. internal_footer: # Footer to append to each email that is sent to non-subscribed addresses. Will # not be included in messages to subscribed addresses. public_footer: # Prefix to be inserted into the subject of every email that is validly signed # by a subscribed address. subject_prefix: # Prefix to be inserted into the subject of every email that is *not* validly # signed by a subscribed address. subject_prefix_in: # Prefix to be inserted into the subject of every email that has been # resent to a non-subscribed address. subject_prefix_out: # Drop any bounces (incoming emails not passing the receive_*_only-rules)? bounces_drop_all: false # Drop bounces if they match one of these headers. Must be a hash, keys # and values are case insensitive. bounces_drop_on_headers: x-spam-flag: yes # Send a notice to the list-admins whenever an email is bounced or dropped? bounces_notify_admins: true # Include Autocrypt header into emails? include_autocrypt_header: true # Include RFC-compliant List-* Headers into emails? include_list_headers: true # Include OpenPGP-Header into emails? include_openpgp_header: true # Preferred way to receive emails to note in OpenPGP-Header # ('sign'|'encrypt'|'signencrypt'|'unprotected'|'none') openpgp_header_preference: signencrypt # Maximum size of emails allowed on the list, in kilobyte. All others will be # bounced. max_message_size_kb: 10240 # How verbose to log on the list-level (Notifications will be sent to # list-admins)? Error, warn, info, or debug. log_level: warn # How many logfiles to keep, including the current one. # Logfiles are rotated daily, so 2 means: delete logfiles older than # yesterday. Values lower than 1 are ignored. logfiles_to_keep: 2 # Which language to use for automated replies, error-messages, etc. # Available: en, de. language: en # Forward a raw copy of all incoming emails to the list-admins? # Mainly useful for debugging. forward_all_incoming_to_admins: false # Should e-mails be delivered to the original subscribed sender? # Disabling this only works for signed e-mails; any e-mail that is unsigned # sent to the list is treated as coming from an unknown source deliver_selfsent: true # Set reply-to header to original sender's reply-to? # Enabling this will set the reply-to-header of emails sent by schleuder # to the original sender's reply-to-header. If the original sender # did not supply a reply-to-header, the original from-header will be used. # This option can enabled for improved usability since this affect # mail client's reply-to button to reply to the original sender instead of # the whole list. set_reply_to_to_sender: false # Munge from-header? # Enabling this option will add the original sender to the from-header. # To avoid DMARC issues, we still use the list's address as from-address. # However the sender's address will be included as displayed name. # For example: "sender@sender.org via list@list.org" # This option can enabled for improved usability since this affect # mail client's displayed name. munge_from: false schleuder-3.6.0/etc/postfix/000077500000000000000000000000001401002544500157405ustar00rootroot00000000000000schleuder-3.6.0/etc/postfix/schleuder_sqlite.cf000066400000000000000000000022151401002544500216110ustar00rootroot00000000000000# Use this as a table for postfix to select addresses that schleuder # thinks belong to it. This is useful when # smtpd_reject_unlisted_recipient = yes (which is the default for # modern Postfix) # For example, you might dedicate Postfix's "virtual" domains to # schleuder with the following set of configs in main.cf: # # virtual_domains = lists.example.org # virtual_transport = schleuder # virtual_alias_maps = hash:/etc/postfix/virtual_aliases # virtual_mailbox_maps = sqlite:/etc/postfix/schleuder_sqlite.cf # schleuder_destination_recipient_limit = 1 # it is not recommended to use this table for more powerful # configuration options (e.g. transport_maps) because it could give # the schleuder user (which can write the given sqlite database) the # power to change settings for for other mail handled by this Postfix # instance. dbpath = /var/lib/schleuder/db.sqlite query = select 'present' from lists where email = '%s' or email = replace('%s', '-bounce@', '@') or email = replace('%s', '-owner@', '@') or email = replace('%s', '-request@', '@') or email = replace('%s', '-sendkey@', '@') schleuder-3.6.0/etc/schleuder-api-daemon.service000066400000000000000000000002731401002544500216160ustar00rootroot00000000000000[Unit] Description=Schleuder API daemon After=local-fs.target network.target [Service] ExecStart=/usr/local/bin/schleuder-api-daemon User=schleuder [Install] WantedBy=multi-user.target schleuder-3.6.0/etc/schleuder.cron.weekly000066400000000000000000000002731401002544500204060ustar00rootroot00000000000000#!/bin/sh test -x /usr/local/bin/schleuder || exit 0 su -s /bin/sh schleuder -c "/usr/local/bin/schleuder refresh_keys" su -s /bin/sh schleuder -c "/usr/local/bin/schleuder check_keys" schleuder-3.6.0/etc/schleuder.yml000066400000000000000000000052051401002544500167470ustar00rootroot00000000000000# Where are the list-directories stored (contain log-files and GnuPG-keyrings). lists_dir: /var/lib/schleuder/lists # Where to write list-logs. The actual log-file will be ///list.log. listlogs_dir: /var/lib/schleuder/lists # Schleuder reads plugins also from this directory. plugins_dir: /etc/schleuder/plugins # Schleuder reads filters also from this directory path, # in the specific pre_decryption or post_decryption subdirectory. # Filter files must follow the following convention for the # filename: \d+_a_name.rb # Where \d+ is any number, that defines the place in the # list of filters and a_name must match the method name # of the filter. # The built-in filters are using round numbers for their # positioning within the list. Increased by ten. filters_dir: /usr/local/lib/schleuder/filters # How verbose should Schleuder log to syslog? (list-specific messages are written to the list's log-file). log_level: warn # Which keyserver to refresh keys from (used by `schleuder refresh_keys`, meant # to be run from cron weekly). # If you have gnupg 2.1, we strongly suggest to use a hkps-keyserver: #keyserver: hkps://hkps.pool.sks-keyservers.net # If you have gnupg 2.1 and TOR running locally, use a onion-keyserver: #keyserver: hkp://jirk5u4osbsr34t5.onion # If you have an OS-wide defined keyserver, specify a blank value to have that # one used: #keyserver: # The default works for all supported versions of gnupg: keyserver: pool.sks-keyservers.net # Who is maintaining the overall schleuder installation and should be # notified about severe problems with lists. # This address should be a postmaster-like account, especially it should # not be another schleuder list. # Is also used as an envelope sender of admin notifications. superadmin: root@localhost # For these options see documentation for ActionMailer::smtp_settings, e.g. . smtp_settings: address: localhost port: 25 #domain: #enable_starttls_auto: #openssl_verify_mode: #authentication: #user_name: #password: # The database to use. Unless you want to run the tests you only need the `production`-section. database: production: adapter: 'sqlite3' database: /var/lib/schleuder/db.sqlite timeout: 5000 api: host: localhost port: 4443 # Certificate and key to use. You can create new ones with `schleuder cert generate`. tls_cert_file: /etc/schleuder/schleuder-certificate.pem tls_key_file: /etc/schleuder/schleuder-private-key.pem # List of api_keys to allow access to the API. # Example: # valid_api_keys: # - abcdef... # - zyxwvu... valid_api_keys: schleuder-3.6.0/lib/000077500000000000000000000000001401002544500142375ustar00rootroot00000000000000schleuder-3.6.0/lib/schleuder-api-daemon.rb000077500000000000000000000034021401002544500205540ustar00rootroot00000000000000#!/usr/bin/env ruby # Make sinatra use production as default-environment ENV['RACK_ENV'] ||= 'production' $LOAD_PATH.unshift(File.expand_path('../../lib', __FILE__)) require 'sinatra/base' require 'sinatra/json' require 'sinatra/namespace' require 'thin' require 'schleuder' require 'schleuder-api-daemon/routes/status' require 'schleuder-api-daemon/routes/version' require 'schleuder-api-daemon/routes/list' require 'schleuder-api-daemon/routes/subscription' require 'schleuder-api-daemon/routes/key' require 'schleuder-api-daemon/helpers/schleuder-api-daemon-helper' %w[tls_cert_file tls_key_file].each do |config_key| path = Conf.api[config_key] if ! File.readable?(path) $stderr.puts "Error: '#{path}' is not a readable file (from #{config_key} in config)." exit 1 end end class SchleuderApiDaemon < Sinatra::Base helpers SchleuderApiDaemonHelper configure do set :server, :thin set :port, Schleuder::Conf.api['port'] || 4443 set :bind, Schleuder::Conf.api['host'] || 'localhost' if settings.development? set :logging, Logger::DEBUG else set :logging, Logger::WARN end end before do authenticate! cast_param_values end after do # Return connection to pool after each request. ActiveRecord::Base.connection.close end error do exc = env['sinatra.error'] logger.error "Error: #{env['sinatra.error'].message}" case exc when Errno::EACCES server_error(exc.message) else client_error(exc.to_s) end end error 404 do 'Not found' end def self.run! super do |server| server.ssl = true server.ssl_options = { :cert_chain_file => Conf.api['tls_cert_file'], :private_key_file => Conf.api['tls_key_file'] } end end end schleuder-3.6.0/lib/schleuder-api-daemon/000077500000000000000000000000001401002544500202255ustar00rootroot00000000000000schleuder-3.6.0/lib/schleuder-api-daemon/helpers/000077500000000000000000000000001401002544500216675ustar00rootroot00000000000000schleuder-3.6.0/lib/schleuder-api-daemon/helpers/schleuder-api-daemon-helper.rb000066400000000000000000000102041401002544500274540ustar00rootroot00000000000000module SchleuderApiDaemonHelper def valid_credentials? @auth ||= Rack::Auth::Basic::Request.new(request.env) if @auth.provided? && @auth.basic? && @auth.credentials.present? username, api_key = @auth.credentials username == 'schleuder' && Conf.api_valid_api_keys.include?(api_key) else false end end def authenticate! # Be careful to use path_info() — it can be changed by other filters! return if request.path_info == '/status.json' if ! valid_credentials? headers['WWW-Authenticate'] = 'Basic realm="Schleuder API Daemon"' halt 401, "Not authorized\n" end end def list(id_or_email=nil) if id_or_email.blank? if params[:list_id].present? id_or_email = params[:list_id] else client_error "Parameter list_id is required" end end if is_an_integer?(id_or_email) list = List.where(id: id_or_email).first else # list_id is actually an email address list = List.where(email: id_or_email).first end list || halt(404) end def subscription(id_or_email) if is_an_integer?(id_or_email) sub = Subscription.where(id: id_or_email.to_i).first else # Email if params[:list_id].blank? client_error "Parameter list_id is required when using email as identifier for subscriptions." else sub = list.subscriptions.where(email: id_or_email).first end end sub || halt(404) end def requested_list_id # ActiveResource doesn't want to use query-params with create(), so here # list_id might be included in the request-body. params['list_id'] || parsed_body['list_id'] || client_error('Need list_id') end def parsed_body @parsed_body ||= begin b = JSON.parse(request.body.read) logger.debug "parsed body: #{b.inspect}" b end end def server_error(msg) logger.warn msg halt(500, json(error: msg)) end # TODO: unify error messages. This method currently sends an old error format. See . def client_error(obj_or_msg, http_code=400) text = case obj_or_msg when String, Symbol obj_or_msg.to_s when ActiveRecord::Base obj_or_msg.errors.full_messages else obj_or_msg end logger.error "Sending error to client: #{text.inspect}" halt(http_code, json(errors: text)) end # poor persons type casting def cast_param_values params.each do |key, value| params[key] = case value when 'true' then true when 'false' then false when '0' then 0 when is_an_integer?(value) then value.to_i else value end end end def key_to_hash(key, include_keydata=false) hash = { fingerprint: key.fingerprint, email: key.email, expiry: key.expires, generated_at: key.generated_at, primary_uid: key.primary_uid.uid, oneline: key.oneline, trust_issues: key.usability_issue } if include_keydata hash[:description] = key.to_s hash[:ascii] = key.armored end hash end def set_x_messages(messages) if messages.present? headers 'X-Messages' => Array(messages).join(' // ').gsub(/\n/, ' // ') end end def find_key_material key_material = parsed_body['key_material'].presence # By convention key_material is either ASCII or base64-encoded. if key_material && ! key_material.match('BEGIN PGP') key_material = Base64.decode64(key_material) end key_material end def find_attributes_from_body(attribs) Array(attribs).inject({}) do |memo, attrib| if parsed_body.has_key?(attrib) memo[attrib] = parsed_body[attrib] end memo end end def is_an_integer?(input) input.to_s.match(/^[0-9]+$/).present? end end schleuder-3.6.0/lib/schleuder-api-daemon/routes/000077500000000000000000000000001401002544500215465ustar00rootroot00000000000000schleuder-3.6.0/lib/schleuder-api-daemon/routes/key.rb000066400000000000000000000014641401002544500226700ustar00rootroot00000000000000class SchleuderApiDaemon < Sinatra::Base register Sinatra::Namespace namespace '/keys' do get '.json' do keys = list.keys.sort_by(&:email).map do |key| key_to_hash(key) end json keys end post '.json' do input = parsed_body['keymaterial'] if ! input.match('BEGIN PGP') input = Base64.decode64(input) end json list(requested_list_id).import_key(input) end get '/check_keys.json' do json result: list.check_keys end get '/:fingerprint.json' do |fingerprint| if key = list.key(fingerprint) json key_to_hash(key, true) else 404 end end delete '/:fingerprint.json' do |fingerprint| if list.delete_key(fingerprint) 200 else 404 end end end end schleuder-3.6.0/lib/schleuder-api-daemon/routes/list.rb000066400000000000000000000030051401002544500230440ustar00rootroot00000000000000class SchleuderApiDaemon < Sinatra::Base register Sinatra::Namespace namespace '/lists' do get '.json' do json List.all, include: :subscriptions end post '.json' do listname = parsed_body['email'] fingerprint = parsed_body['fingerprint'] adminaddress = parsed_body['adminaddress'] adminfingerprint = parsed_body['adminfingerprint'] adminkey = parsed_body['adminkey'] list, messages = ListBuilder.new({email: listname, fingerprint: fingerprint}, adminaddress, adminfingerprint, adminkey).run if list.nil? client_error(messages, 422) elsif ! list.valid? client_error(list, 422) else set_x_messages(messages) body json(list) end end get '/configurable_attributes.json' do json(List.configurable_attributes) + "\n" end post '/send_list_key_to_subscriptions.json' do json(result: list.send_list_key_to_subscriptions) end get '/new.json' do json List.new end get '/:id.json' do |id| json list(id) end put '/:id.json' do |id| list = list(id) if list.update(parsed_body) 204 else client_error(list) end end patch '/:id.json' do |id| list = list(id) if list.update(parsed_body) 204 else client_error(list) end end delete '/:id.json' do |id| list = list(id) if list.destroy 200 else client_error(list) end end end end schleuder-3.6.0/lib/schleuder-api-daemon/routes/status.rb000066400000000000000000000001401401002544500234110ustar00rootroot00000000000000class SchleuderApiDaemon < Sinatra::Base get '/status.json' do json status: :ok end end schleuder-3.6.0/lib/schleuder-api-daemon/routes/subscription.rb000066400000000000000000000052351401002544500246240ustar00rootroot00000000000000class SchleuderApiDaemon < Sinatra::Base register Sinatra::Namespace namespace '/subscriptions' do get '.json' do filterkeys = Subscription.configurable_attributes + [:list_id, :email] filter = params.select do |param| filterkeys.include?(param.to_sym) end logger.debug "Subscription filter: #{filter.inspect}" if filter['list_id'] && ! is_an_integer?(filter['list_id']) # Value is an email-address if list = List.where(email: filter['list_id']).first filter['list_id'] = list.id else status 404 return json(errors: 'No such list') end end json Subscription.where(filter) end post '.json' do begin list = list(requested_list_id) # We don't have to care about nil-values, subscribe() does that for us. sub, msgs = list.subscribe( parsed_body['email'], parsed_body['fingerprint'], parsed_body['admin'], parsed_body['delivery_enabled'], find_key_material ) set_x_messages(msgs) logger.debug "subcription: #{sub.inspect}" if sub.valid? logger.debug "Subscribed: #{sub.inspect}" # TODO: why redirect instead of respond with result? redirect to("/subscriptions/#{sub.id}.json"), 201 else client_error(sub, 422) end rescue ActiveRecord::RecordNotUnique logger.error "Already subscribed" status 422 json errors: {email: ['is already subscribed']} end end get '/configurable_attributes.json' do json(Subscription.configurable_attributes) + "\n" end get '/new.json' do json Subscription.new end get '/:id.json' do |id| json subscription(id) end put '/:id.json' do |id| sub = subscription(id) list = sub.list args = find_attributes_from_body(%w[email fingerprint admin delivery_enabled]) fingerprint, messages = list.import_key_and_find_fingerprint(find_key_material) set_x_messages(messages) # For an already existing subscription, only update fingerprint if a # new one has been selected from the upload. if fingerprint.present? args["fingerprint"] = fingerprint end if sub.update(args) 200 else client_error(sub, 422) end end patch '/:id.json' do |id| sub = subscription(id) if sub.update(parsed_body) 200 else client_error(sub) end end delete '/:id.json' do |id| if sub = subscription(id).destroy 200 else client_error(sub) end end end end schleuder-3.6.0/lib/schleuder-api-daemon/routes/version.rb000066400000000000000000000001611401002544500235560ustar00rootroot00000000000000class SchleuderApiDaemon < Sinatra::Base get '/version.json' do json version: Schleuder::VERSION end end schleuder-3.6.0/lib/schleuder.rb000066400000000000000000000050121401002544500165400ustar00rootroot00000000000000# default to UTF-8 encoding as early as possible for external # data. # # this should ensure we are able to parse most incoming # plain text mails in different charsets. Encoding.default_external = Encoding::UTF_8 # Stdlib require 'fileutils' require 'singleton' require 'yaml' require 'pathname' require 'syslog/logger' require 'logger' require 'open3' # Require mandatory libs. The database-layer-lib is required below. require 'mail-gpg' require 'active_record' # An extra from mail-gpg require 'hkp' # Load schleuder libdir = Pathname.new(__FILE__).dirname.realpath rootdir = libdir.dirname $:.unshift libdir # Monkeypatches require 'schleuder/mail/parts_list.rb' require 'schleuder/mail/message.rb' require 'schleuder/mail/gpg.rb' require 'schleuder/mail/encrypted_part.rb' require 'schleuder/gpgme/import_status.rb' require 'schleuder/gpgme/key.rb' require 'schleuder/gpgme/sub_key.rb' require 'schleuder/gpgme/ctx.rb' require 'schleuder/gpgme/user_id.rb' # The Code[tm] require 'schleuder/errors/base' Dir["#{libdir}/schleuder/errors/*.rb"].each do |file| require file end # Load schleuder/conf before the other classes, it defines constants! require 'schleuder/conf' require 'schleuder/version' require 'schleuder/logger_notifications' require 'schleuder/logger' require 'schleuder/listlogger' require 'schleuder/plugin_runners/base' require 'schleuder/plugin_runners/list_plugins_runner' require 'schleuder/plugin_runners/request_plugins_runner' Dir["#{libdir}/schleuder/plugins/*.rb"].each do |file| require file end require 'schleuder/filters_runner' Dir["#{libdir}/schleuder/validators/*.rb"].each do |file| require file end require 'schleuder/runner' require 'schleuder/list' require 'schleuder/list_builder' require 'schleuder/subscription' # Setup ENV["SCHLEUDER_CONFIG"] ||= '/etc/schleuder/schleuder.yml' ENV["SCHLEUDER_LIST_DEFAULTS"] ||= '/etc/schleuder/list-defaults.yml' ENV["SCHLEUDER_ENV"] ||= 'production' ENV["SCHLEUDER_ROOT"] = rootdir.to_s # Ensure that gnupg never-ever tries to ask for a passphrase. ENV["GPG_TTY"] = "/nonexistant-#{rand}" ENV["DISPLAY"] = nil GPGME::Ctx.set_gpg_path_from_env GPGME::Ctx.check_gpg_version # TODO: Test if database is writable if sqlite. ActiveRecord::Base.establish_connection(Schleuder::Conf.database) ActiveRecord::Base.logger = Schleuder.logger Mail.defaults do delivery_method :smtp, Schleuder::Conf.smtp_settings.symbolize_keys end I18n.load_path += Dir["#{rootdir}/locales/*.yml"] I18n.enforce_available_locales = true I18n.default_locale = :en File.umask(0027) include Schleuder schleuder-3.6.0/lib/schleuder/000077500000000000000000000000001401002544500162155ustar00rootroot00000000000000schleuder-3.6.0/lib/schleuder/cli.rb000066400000000000000000000300521401002544500173110ustar00rootroot00000000000000require 'thor' require 'yaml' require 'gpgme' require 'charlock_holmes' require_relative '../schleuder' require 'schleuder/cli/subcommand_fix' require 'schleuder/cli/schleuder_cert_manager' require 'schleuder/cli/cert' module Schleuder class Cli < Thor register(Cert, 'cert', 'cert ...', 'Generate TLS-certificate and show fingerprint') map '-v' => :version map '--version' => :version desc 'version', 'Show version of schleuder' def version say Schleuder::VERSION end desc 'new_api_key', 'Generate a new API key to be used by a client.' def new_api_key require 'securerandom' puts SecureRandom.hex(32) end desc 'work list@hostname < message', 'Run a message through a list.' def work(listname) message = STDIN.read error = Schleuder::Runner.new.run(message, listname) if error.kind_of?(StandardError) fatal error end rescue => exc begin Schleuder.logger.fatal(exc.message_with_backtrace, message) # Don't use FatalError here to reduce dependency on other code. say I18n.t('errors.fatalerror') rescue => e # Give users a clue what to do in case everything blows up. # As apparently even the logging raised exceptions we can't even store # any information in the logs. fatal "A serious, unhandleable error happened. Please contact the administrators of this system or service and provide them with the following information:\n\n#{e.message}" end exit 1 end desc 'check_keys', 'Check all lists for unusable or expiring keys and send the results to the list-admins. (This is supposed to be run from cron weekly.)' def check_keys List.all.each do |list| I18n.locale = list.language text = list.check_keys if text && ! text.empty? msg = "#{I18n.t('check_keys_intro', email: list.email)}\n\n#{text}" list.logger.notify_admin(msg, nil, I18n.t('check_keys')) end end permission_notice end desc 'refresh_keys [list1@example.com]', "Refresh all keys of all list from the keyservers sequentially (one by one or on the passed list). (This is supposed to be run from cron weekly.)" def refresh_keys(list=nil) GPGME::Ctx.send_notice_if_gpg_does_not_know_import_filter work_on_lists(:refresh_keys,list) permission_notice end desc 'pin_keys [list1@example.com]', "Find keys for subscriptions without a pinned key and try to pin a certain key (one by one or based on the passed list)." def pin_keys(list=nil) work_on_lists(:pin_keys,list) end desc 'install', "Set-up or update Schleuder environment (create folders, copy files, fill the database)." def install config_dir = Pathname.new(ENV['SCHLEUDER_CONFIG']).dirname root_dir = Pathname.new(ENV['SCHLEUDER_ROOT']) # Check if lists_dir contains v2-data. if Dir.glob("#{Conf.lists_dir}/*/*/members.conf").size > 0 msg = "Lists directory #{Conf.lists_dir} appears to contain data from a Schleuder version 2.x installation.\nPlease move it out of the way or configure a different `lists_dir` in `#{ENV['SCHLEUDER_CONFIG']}`.\nTo migrate lists from Schleuder v2 to Schleuder v3 please use `schleuder migrate_v2_list` after the installation succeeded." fatal msg, 2 end [Conf.lists_dir, Conf.listlogs_dir, config_dir].each do |dir| dir = Pathname.new(dir) if ! dir.exist? begin dir.mkpath rescue Errno::EACCES => exc problem_dir = exc.message.split(' - ').last fatal "Cannot create required directory due to lacking write permissions: #{problem_dir}.\nPlease fix the permissions or create the directory manually and then run this command again." end end end Pathname.glob(root_dir.join("etc").join("*.yml")).each do |file| target = config_dir.join(file.basename) if ! target.exist? if target.dirname.writable? FileUtils.cp file, target else fatal "Cannot copy default config file due to lacking write permissions, please copy manually and then run this command again:\n#{file.realpath} → #{target}" end end end if ActiveRecord::SchemaMigration.table_exists? say shellexec("cd #{root_dir} && rake db:migrate") else say shellexec("cd #{root_dir} && rake db:init") if Conf.database['adapter'].match(/sqlite/) say "NOTE: The database was prepared using sqlite. If you prefer to use a different DBMS please edit the 'database'-section in /etc/schleuder/schleuder.yml, create the database, install the corresponding ruby-library (e.g. `gem install mysql`) and run this current command again" end end if ! File.exist?(Conf.api['tls_cert_file']) || ! File.exist?(Conf.api['tls_key_file']) Schleuder::Cert.new.generate end say "Schleuder has been set up. You can now create a new list using `schleuder-cli`.\nWe hope you enjoy!" permission_notice rescue => exc fatal exc.message end desc 'migrate-v2-list /path/to/listdir', 'Migrate list from v2.2 to v3.' def migrate_v2_list(path) dir = Pathname.new(path) if ! dir.readable? || ! dir.directory? fatal "Not a readable directory: `#{path}`." end %w[list.conf members.conf pubring.gpg].each do |file| if ! (dir + file).exist? fatal "Not a complete schleuder v2.2 listdir: missing #{file}" end end conf = YAML.load(File.read(dir + 'list.conf')) if conf.nil? || conf.empty? fatal "list.conf is blank" end listname = conf['myaddr'] if listname.nil? || listname.empty? fatal "myaddr is blank in list.conf" end # Identify list-fingerprint. ENV['GNUPGHOME'] = dir.to_s listkey = GPGME::Key.find(:public, "<#{listname}>").first if listkey.nil? fatal "Failed to identify the list's OpenPGP-key!" end # Create list. begin list, messages = Schleuder::ListBuilder.new({email: listname, fingerprint: listkey.fingerprint}).run rescue => exc fatal exc end if messages fatal messages.values.join(" - ") elsif list.errors.any? fatal list.errors.full_messages.join(" - ") end # Import keys list.import_key(File.read(dir + 'pubring.gpg')) list.import_key(File.read(dir + 'secring.gpg')) # Clear passphrase of imported list-key. output = list.key.clearpassphrase(conf['gpg_password']) if output.present? fatal "while clearing passphrase of list-key: #{output.inspect}" end # Set list-options. List.configurable_attributes.each do |option| option = option.to_s if conf.keys.include?(option) value = case option when /^keywords_/ filter_keywords(conf[option]) when 'log_level' conf[option].to_s.downcase else conf[option] end list.set_attribute(option, value) end end # Set changed options. changed_options = { 'prefix' => 'subject_prefix', 'prefix_in' => 'subject_prefix_in', 'prefix_out' => 'subject_prefix_out', 'dump_incoming_mail' => 'forward_all_incoming_to_admins', 'receive_from_member_emailaddresses_only' => 'receive_from_subscribed_emailaddresses_only', 'bounces_notify_admin' => 'bounces_notify_admins', 'max_message_size' => 'max_message_size_kb' } changed_options.each do |old, new| if conf.keys.include?(old) list.set_attribute(new, conf[old]) end end list.save! # Subscribe members members = YAML.load(File.read(dir + 'members.conf')) members.uniq!{|m| m['email'] } members.each do |member| fingerprint = find_fingerprint(member, list) list.subscribe(member['email'], fingerprint) end # Subscribe or flag admins conf['admins'].each do |member| sub = list.subscriptions.where(email: member['email']).first if sub sub.admin = true sub.save! else adminfpr = find_fingerprint(member, list) # if we didn't find an already imported subscription for the admin # address, it wasn't a member, so we don't enable delivery for it list.subscribe(member['email'], adminfpr, true, false) end end # Notify of removed options say "Please note: the following options have been *removed*: * `default_mime` for lists (we only support pgp/mime for now), * `archive` for lists, * `gpg_passphrase` for lists, * `log_file`, `log_io`, `log_syslog` for lists (we only log to syslog (before list-creation) and a file (after it) for now), * `mime` for subscriptions/members (we only support pgp/mime for now), * `send_encrypted_only` for members/subscriptions. If you really miss any of them please tell us. Please also note that the following keywords have been renamed: * list-members => list-subscriptions * add-member => subscribe * delete-member => unsubscribe Please notify the users and admins of this list of these changes. " say "\nList #{listname} migrated to schleuder v3." if messages.present? say messages.gsub(' // ', "\n") end permission_notice rescue => exc fatal "#{exc}\n#{exc.backtrace.first}" end no_commands do def fatal(msg, exitcode=1) error("Error: #{msg}") exit exitcode end KEYWORDS = { 'add-member' => 'subscribe', 'delete-member' => 'unsubscribe', 'list-members' => 'list-subscriptions', 'subscribe' => 'subscribe', 'unsubscribe' => 'unsubscribe', 'list-subscriptions' => 'list-subscriptions', 'set-finterprint' => 'set-fingerprint', 'add-key' => 'add-key', 'delete-key' => 'delete-key', 'list-keys' => 'list-keys', 'get-key' => 'get-key', 'fetch-key' => 'fetch-key' } def filter_keywords(value) Array(value).map do |keyword| KEYWORDS[keyword.downcase] end.compact end def find_fingerprint(member, list) email = member['email'] fingerprint = member['key_fingerprint'] if fingerprint.present? return fingerprint end key = list.distinct_key(email) if key return key.fingerprint else return nil end end def shellexec(cmd) result = `#{cmd} 2>&1` if $?.exitstatus > 0 exit $?.exitstatus end result end end private def work_on_lists(subj, list=nil) if list.nil? selected_lists = List.all else selected_lists = List.where(email: list) if selected_lists.blank? error("No list with this address exists: #{list.inspect}") end end selected_lists.each do |list| I18n.locale = list.language output = list.send(subj) if output.present? msg = "#{I18n.t("#{subj}_intro", email: list.email)}\n\n#{output}" list.logger.notify_admin(msg, nil, I18n.t(subj)) end end end # Make this class exit with code 1 in case of an error. See . def self.exit_on_failure? true end def permission_notice if Process.euid == 0 dirs = [Conf.lists_dir, Conf.listlogs_dir] if Conf.database['adapter'] == 'sqlite3' dirs << Conf.database['database'] end dirs_sentence = dirs.uniq.map { |dir| enquote(dir) }.to_sentence say "Warning: this process was run as root -- please make sure that all files in #{dirs_sentence} have correct file system permissions for the user that is running both, schleuder from the MTA and `schleuder-api-daemon`." end end def enquote(string) "\`#{string}\`" end end end schleuder-3.6.0/lib/schleuder/cli/000077500000000000000000000000001401002544500167645ustar00rootroot00000000000000schleuder-3.6.0/lib/schleuder/cli/cert.rb000066400000000000000000000017051401002544500202510ustar00rootroot00000000000000module Schleuder class Cert < Thor extend SubcommandFix desc 'generate', 'Generate a new TLS-certificate.' def generate key = Conf.api['tls_key_file'] cert = Conf.api['tls_cert_file'] fingerprint = SchleuderCertManager.generate('schleuder', key, cert) puts "Fingerprint of generated certificate: #{fingerprint}" puts "Have this fingerprint included into the configuration-file of all clients that want to connect to your Schleuder API." if Process.euid == 0 puts "! Warning: this process was run as root — please make sure the above files are accessible by the user that is running `schleuder-api-daemon`." end end desc 'fingerprint', 'Show fingerprint of configured certificate.' def fingerprint cert = Conf.api['tls_cert_file'] fingerprint = SchleuderCertManager.fingerprint(cert) say "Fingerprint of #{Conf.api['tls_cert_file']}: #{fingerprint}" end end end schleuder-3.6.0/lib/schleuder/cli/schleuder_cert_manager.rb000066400000000000000000000046421401002544500240040ustar00rootroot00000000000000require 'openssl' require 'pathname' class SchleuderCertManager def self.generate(project_name, filename_key, filename_cert) keysize = 2048 subject = "/C=MW/O=Schleuder/OU=#{project_name}" filename_key = Pathname.new(filename_key).expand_path filename_cert = Pathname.new(filename_cert).expand_path key = OpenSSL::PKey::RSA.new(keysize) cert = OpenSSL::X509::Certificate.new cert.subject = OpenSSL::X509::Name.parse(subject) cert.issuer = cert.subject cert.not_before = Time.now cert.not_after = Time.now + 10 * 365 * 24 * 60 * 60 cert.public_key = key.public_key cert.serial = 0x0 cert.version = 2 ef = OpenSSL::X509::ExtensionFactory.new ef.subject_certificate = cert ef.issuer_certificate = cert cert.extensions = [ ef.create_extension("basicConstraints","CA:TRUE", true), ef.create_extension("subjectKeyIdentifier", "hash"), ] cert.add_extension ef.create_extension("authorityKeyIdentifier", "keyid:always,issuer:always") cert.sign key, OpenSSL::Digest::SHA256.new filename_key = prepare_writing(filename_key) filename_cert = prepare_writing(filename_cert) filename_key.open('w', 400) do |fd| fd.puts key end puts "Private key written to: #{filename_key}" filename_cert.open('w') do |fd| fd.puts cert.to_pem end puts "Certificate written to: #{filename_cert}" fingerprint(cert) rescue => exc error exc.message end def self.fingerprint(cert) if ! cert.is_a?(OpenSSL::X509::Certificate) path = Pathname.new(cert).expand_path if ! path.readable? error "Error: Not a readable file: #{path}" end cert = OpenSSL::X509::Certificate.new(path.read) end OpenSSL::Digest::SHA256.new(cert.to_der).to_s end def self.error(msg) $stderr.puts "Error: #{msg}" exit 1 end def self.note(msg) $stdout.puts "Note: #{msg}" end def self.prepare_writing(filename) if filename.exist? note "File exists: #{filename} — writing to current directory, you should move the file manually or change the configuration file." if filename.basename.exist? error "File exists: #{filename.basename} — (re)move it or fix previous error and try again." end filename = filename.basename end if ! filename.dirname.exist? filename.dirname.mkpath end filename end end schleuder-3.6.0/lib/schleuder/cli/subcommand_fix.rb000066400000000000000000000005071401002544500223110ustar00rootroot00000000000000module Schleuder module SubcommandFix # Fixing a bug in Thor where the actual subcommand wouldn't show up # with some invocations of the help-output. def banner(task, namespace = true, subcommand = true) "#{basename} #{task.formatted_usage(self, true, subcommand).split(':').join(' ')}" end end end schleuder-3.6.0/lib/schleuder/conf.rb000066400000000000000000000071341401002544500174740ustar00rootroot00000000000000require 'erb' module Schleuder class Conf include Singleton # since the regexp got only included into stdlib 2.2 # TODO: remove once 2.1 support dropped if RUBY_VERSION < '2.2' EMAIL_REGEXP = /\A[a-zA-Z0-9.!\#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*\z/ else EMAIL_REGEXP = URI::MailTo::EMAIL_REGEXP end # TODO: drop v3 keys and only accept length of 40 FINGERPRINT_REGEXP = /\A(0x)?[a-f0-9]{32}([a-f0-9]{8})?\z/i DEFAULTS = { 'lists_dir' => '/var/lib/schleuder/lists', 'listlogs_dir' => '/var/lib/schleuder/lists', 'plugins_dir' => '/etc/schleuder/plugins', 'filters_dir' => '/usr/local/lib/schleuder/filters', 'log_level' => 'warn', 'superadmin' => 'root@localhost', 'keyserver' => 'hkp://pool.sks-keyservers.net', 'smtp_settings' => { 'address' => 'localhost', 'port' => 25, 'domain' => 'localhost', 'enable_starttls_auto' => true, # Don't verify by default because most smtp servers don't include # 'localhost' into their TLS-certificates. 'openssl_verify_mode' => 'none', 'authentication' => nil, 'user_name' => nil, 'password' => nil, }, 'database' => { 'production' => { 'adapter' => 'sqlite3', 'database' => '/var/lib/schleuder/db.sqlite', 'timeout' => 5000 } }, 'api' => { 'host' => 'localhost', 'port' => 4443, 'tls_cert_file' => '/etc/schleuder/schleuder-certificate.pem', 'tls_key_file' => '/etc/schleuder/schleuder-private-key.pem', 'valid_api_keys' => [] } } def config @config ||= load_config(ENV['SCHLEUDER_CONFIG']) end def self.lists_dir instance.config['lists_dir'] end def self.listlogs_dir instance.config['listlogs_dir'] end def self.plugins_dir instance.config['plugins_dir'] end def self.filters_dir instance.config['filters_dir'] end def self.database instance.config['database'][ENV['SCHLEUDER_ENV']] end def self.databases instance.config['database'] end def self.superadmin instance.config['superadmin'] end def self.log_level instance.config['log_level'] || 'WARN' end def self.api instance.config['api'] || {} end def self.api_valid_api_keys Array(api['valid_api_keys']) end # Three legacy options def self.smtp_host instance.config['smtp_host'] end def self.smtp_port instance.config['smtp_port'] end def self.smtp_helo_domain instance.config['smtp_helo_domain'] end def self.smtp_settings settings = instance.config['smtp_settings'] || {} # Support previously used config-options. # Remove this in future versions. {smtp_host: :address, smtp_port: :port, smtp_helo_domain: :domain}.each do |old, new| value = self.send(old) if value.present? Schleuder.logger.warn "Deprecation warning: In schleuder.yml #{old} should be changed to smtp_settings[#{new}]." settings[new] = value end end settings end def self.keyserver instance.config['keyserver'] end private def load_config(filename) DEFAULTS.deep_merge(load_config_file(filename)) end def load_config_file(filename) file = Pathname.new(filename) if file.readable? YAML.load(ERB.new(file.read).result) else {} end end end end schleuder-3.6.0/lib/schleuder/errors/000077500000000000000000000000001401002544500175315ustar00rootroot00000000000000schleuder-3.6.0/lib/schleuder/errors/active_model_error.rb000066400000000000000000000003721401002544500237240ustar00rootroot00000000000000module Schleuder module Errors class ActiveModelError < Base def initialize(errors) messages = errors.messages.map do |message| message.join(' ') end.join("\n") super messages end end end end schleuder-3.6.0/lib/schleuder/errors/base.rb000066400000000000000000000004251401002544500207710ustar00rootroot00000000000000module Schleuder module Errors class Base < StandardError def t(*args) I18n.t(*args) end def to_s super + t('errors.signoff') end def set_default_locale I18n.locale = I18n.default_locale end end end end schleuder-3.6.0/lib/schleuder/errors/decryption_failed.rb000066400000000000000000000004121401002544500235370ustar00rootroot00000000000000module Schleuder module Errors class DecryptionFailed < Base def initialize(list) set_default_locale super t('errors.decryption_failed', { key: list.key.to_s, email: list.sendkey_address }) end end end end schleuder-3.6.0/lib/schleuder/errors/fatal_error.rb000066400000000000000000000002501401002544500223530ustar00rootroot00000000000000module Schleuder module Errors class FatalError < Base def initialize end def to_s t("errors.fatalerror") end end end end schleuder-3.6.0/lib/schleuder/errors/key_adduid_failed.rb000066400000000000000000000002731401002544500234660ustar00rootroot00000000000000module Schleuder module Errors class KeyAdduidFailed < Base def initialize(errmsg) super t('errors.key_adduid_failed', { errmsg: errmsg }) end end end end schleuder-3.6.0/lib/schleuder/errors/key_generation_failed.rb000066400000000000000000000003421401002544500243640ustar00rootroot00000000000000module Schleuder module Errors class KeyGenerationFailed < Base def initialize(listdir, listname) super t('errors.key_generation_failed', {listdir: listdir, listname: listname}) end end end end schleuder-3.6.0/lib/schleuder/errors/keyword_admin_only.rb000066400000000000000000000002741401002544500237560ustar00rootroot00000000000000module Schleuder module Errors class KeywordAdminOnly < Base def initialize(keyword) super t('errors.keyword_admin_only', keyword: keyword) end end end end schleuder-3.6.0/lib/schleuder/errors/list_not_found.rb000066400000000000000000000002671401002544500231110ustar00rootroot00000000000000module Schleuder module Errors class ListNotFound < Base def initialize(recipient) super t('errors.list_not_found', email: recipient) end end end end schleuder-3.6.0/lib/schleuder/errors/list_property_missing.rb000066400000000000000000000004351401002544500245300ustar00rootroot00000000000000module Schleuder module Errors class ListPropertyMissing < Base def initialize(listdir, property) @listdir = listdir @property = property end def to_s t("errors.list_#{@property}_missing", listdir: @listdir) end end end end schleuder-3.6.0/lib/schleuder/errors/listdir_problem.rb000066400000000000000000000004101401002544500232430ustar00rootroot00000000000000module Schleuder module Errors class ListdirProblem < Base def initialize(dir, problem) problem = t("errors.listdir_problem.#{problem}") super t('errors.listdir_problem.message', dir: dir, problem: problem) end end end end schleuder-3.6.0/lib/schleuder/errors/loading_list_settings_failed.rb000066400000000000000000000004041401002544500257500ustar00rootroot00000000000000module Schleuder module Errors class LoadingListSettingsFailed < Base def initialize config_file = ENV['SCHLEUDER_LIST_DEFAULTS'] super t('errors.loading_list_settings_failed', config_file: config_file) end end end end schleuder-3.6.0/lib/schleuder/errors/message_empty.rb000066400000000000000000000003441401002544500227210ustar00rootroot00000000000000module Schleuder module Errors class MessageEmpty < Base def initialize(list) set_default_locale super t('errors.message_empty', { request_address: list.request_address }) end end end end schleuder-3.6.0/lib/schleuder/errors/message_not_from_admin.rb000066400000000000000000000003031401002544500245510ustar00rootroot00000000000000module Schleuder module Errors class MessageNotFromAdmin < Base def initialize set_default_locale super t('errors.message_not_from_admin') end end end end schleuder-3.6.0/lib/schleuder/errors/message_sender_not_subscribed.rb000066400000000000000000000003211401002544500261230ustar00rootroot00000000000000module Schleuder module Errors class MessageSenderNotSubscribed < Base def initialize set_default_locale super t('errors.message_sender_not_subscribed') end end end end schleuder-3.6.0/lib/schleuder/errors/message_too_big.rb000066400000000000000000000004141401002544500232030ustar00rootroot00000000000000module Schleuder module Errors class MessageTooBig < Base def initialize(list) set_default_locale allowed_size = list.max_message_size_kb super t('errors.message_too_big', { allowed_size: allowed_size }) end end end end schleuder-3.6.0/lib/schleuder/errors/message_unauthenticated.rb000066400000000000000000000003071401002544500247470ustar00rootroot00000000000000module Schleuder module Errors class MessageUnauthenticated < Base def initialize set_default_locale super t('errors.message_unauthenticated') end end end end schleuder-3.6.0/lib/schleuder/errors/message_unencrypted.rb000066400000000000000000000002771401002544500241300ustar00rootroot00000000000000module Schleuder module Errors class MessageUnencrypted < Base def initialize set_default_locale super t('errors.message_unencrypted') end end end end schleuder-3.6.0/lib/schleuder/errors/message_unsigned.rb000066400000000000000000000002711401002544500233760ustar00rootroot00000000000000module Schleuder module Errors class MessageUnsigned < Base def initialize set_default_locale super t('errors.message_unsigned') end end end end schleuder-3.6.0/lib/schleuder/errors/standard_error.rb000066400000000000000000000001541401002544500230670ustar00rootroot00000000000000class StandardError def message_with_backtrace "#{message}\n#{self.backtrace.join("\n")}\n" end end schleuder-3.6.0/lib/schleuder/errors/too_many_keys.rb000066400000000000000000000003231401002544500227340ustar00rootroot00000000000000module Schleuder module Errors class TooManyKeys < Base def initialize(listdir, listname) super t('errors.too_many_keys', {listdir: listdir, listname: listname}) end end end end schleuder-3.6.0/lib/schleuder/filters/000077500000000000000000000000001401002544500176655ustar00rootroot00000000000000schleuder-3.6.0/lib/schleuder/filters/post_decryption/000077500000000000000000000000001401002544500231125ustar00rootroot00000000000000schleuder-3.6.0/lib/schleuder/filters/post_decryption/10_request.rb000066400000000000000000000013071401002544500254300ustar00rootroot00000000000000module Schleuder module Filters def self.request(list, mail) return if ! mail.request? list.logger.debug "Request-message" if ! mail.was_encrypted? || ! mail.was_validly_signed? list.logger.debug "Error: Message was not encrypted and validly signed" return Errors::MessageUnauthenticated.new end if mail.keywords.empty? output = I18n.t(:no_keywords_error) else output = PluginRunners::RequestPluginsRunner.run(list, mail) output = output.flatten.map(&:presence).compact if output.blank? output = I18n.t(:no_output_result) end end mail.reply_to_signer(output) exit end end end schleuder-3.6.0/lib/schleuder/filters/post_decryption/20_max_message_size.rb000066400000000000000000000004221401002544500272610ustar00rootroot00000000000000module Schleuder module Filters def self.max_message_size(list, mail) if (mail.raw_source.size / 1024) > list.max_message_size_kb list.logger.info "Rejecting mail as too big" return Errors::MessageTooBig.new(list) end end end end schleuder-3.6.0/lib/schleuder/filters/post_decryption/30_forward_to_owner.rb000066400000000000000000000006711401002544500273250ustar00rootroot00000000000000module Schleuder module Filters def self.forward_to_owner(list, mail) return if ! mail.to_owner? list.logger.debug "Forwarding addressed to -owner" mail.add_pseudoheader(:note, I18n.t(:owner_forward_prefix)) cleanmail = mail.clean_copy(true) list.admins.each do |admin| list.logger.debug "Forwarding message to #{admin}" admin.send_mail(cleanmail) end exit end end end schleuder-3.6.0/lib/schleuder/filters/post_decryption/40_receive_admin_only.rb000066400000000000000000000004621401002544500275770ustar00rootroot00000000000000module Schleuder module Filters def self.receive_admin_only(list, mail) if list.receive_admin_only? && ( ! mail.was_validly_signed? || ! mail.signer.admin? ) list.logger.info "Rejecting mail as not from admin." return Errors::MessageNotFromAdmin.new end end end end schleuder-3.6.0/lib/schleuder/filters/post_decryption/50_receive_authenticated_only.rb000066400000000000000000000005061401002544500313310ustar00rootroot00000000000000module Schleuder module Filters def self.receive_authenticated_only(list, mail) if list.receive_authenticated_only? && ( ! mail.was_encrypted? || ! mail.was_validly_signed? ) list.logger.info "Rejecting mail as unauthenticated" return Errors::MessageUnauthenticated.new end end end end schleuder-3.6.0/lib/schleuder/filters/post_decryption/60_receive_signed_only.rb000066400000000000000000000004151401002544500277600ustar00rootroot00000000000000module Schleuder module Filters def self.receive_signed_only(list, mail) if list.receive_signed_only? && ! mail.was_validly_signed? list.logger.info "Rejecting mail as unsigned" return Errors::MessageUnsigned.new end end end end schleuder-3.6.0/lib/schleuder/filters/post_decryption/70_receive_encrypted_only.rb000066400000000000000000000004241401002544500305050ustar00rootroot00000000000000module Schleuder module Filters def self.receive_encrypted_only(list, mail) if list.receive_encrypted_only? && ! mail.was_encrypted? list.logger.info "Rejecting mail as unencrypted" return Errors::MessageUnencrypted.new end end end end 80_receive_from_subscribed_emailaddresses_only.rb000066400000000000000000000005711401002544500346520ustar00rootroot00000000000000schleuder-3.6.0/lib/schleuder/filters/post_decryptionmodule Schleuder module Filters def self.receive_from_subscribed_emailaddresses_only(list, mail) if list.receive_from_subscribed_emailaddresses_only? && list.subscriptions.where(email: mail.from.first).blank? list.logger.info "Rejecting mail as not from subscribed address." return Errors::MessageSenderNotSubscribed.new end end end end 90_strip_html_from_alternative_if_keywords_present.rb000066400000000000000000000012331401002544500356420ustar00rootroot00000000000000schleuder-3.6.0/lib/schleuder/filters/post_decryptionmodule Schleuder module Filters def self.strip_html_from_alternative_if_keywords_present(list, mail) if mail[:content_type].blank? || mail[:content_type].content_type != 'multipart/alternative' || mail.keywords.blank? return false end Schleuder.logger.debug 'Stripping html-part from multipart/alternative-message because it contains keywords' mail.parts.delete_if do |part| part[:content_type].content_type == 'text/html' end mail.content_type = 'multipart/mixed' mail.add_pseudoheader(:note, I18n.t('pseudoheaders.stripped_html_from_multialt_with_keywords')) end end end schleuder-3.6.0/lib/schleuder/filters/pre_decryption/000077500000000000000000000000001401002544500227135ustar00rootroot00000000000000schleuder-3.6.0/lib/schleuder/filters/pre_decryption/10_forward_bounce_to_admins.rb000066400000000000000000000005531401002544500305770ustar00rootroot00000000000000module Schleuder module Filters def self.forward_bounce_to_admins(list, mail) if mail.automated_message? list.logger.info "Forwarding automated message to admins" list.logger.notify_admin I18n.t(:forward_automated_message_to_admins), mail.original_message, I18n.t('automated_message_subject') exit end end end end schleuder-3.6.0/lib/schleuder/filters/pre_decryption/20_forward_all_incoming_to_admins.rb000066400000000000000000000004431401002544500317560ustar00rootroot00000000000000module Schleuder module Filters def self.forward_all_incoming_to_admins(list, mail) if list.forward_all_incoming_to_admins list.logger.notify_admin I18n.t(:forward_all_incoming_to_admins), mail.original_message, I18n.t('incoming_message') end end end end schleuder-3.6.0/lib/schleuder/filters/pre_decryption/30_send_key.rb000066400000000000000000000011501401002544500253400ustar00rootroot00000000000000module Schleuder module Filters def self.send_key(list, mail) return if ! mail.sendkey_request? list.logger.debug "Sending public key as reply." out = mail.reply out.from = list.email # We're not sending to a subscribed address, so we need to specify a envelope-sender manually. out.sender = list.bounce_address out.body = I18n.t(:list_public_key_attached) out.attach_list_key!(list) # TODO: find out why the gpg-module puts all the headers into the first mime-part, too out.gpg list.gpg_sign_options out.deliver exit end end end schleuder-3.6.0/lib/schleuder/filters/pre_decryption/40_fix_exchange_messages.rb000066400000000000000000000024421401002544500300640ustar00rootroot00000000000000module Schleuder module Filters # Outlook / Hotmail seems to dismantle multipart/encrypted messages and # put them again together as multipart/mixed, which is wrong and makes # it problematic to correctly detect the message as a valid pgp/mime-mail. # Here we fix the mail to be a proper pgp/mime aka. multipart/encrypted # message, so further processing will detect it properly. # This problem seems to be in fact related to the use of Microsoft # Exchange. Accordingly, check if the headers contain 'X-MS-Exchange'. # See #211, #246, #331 and #333 for background. def self.fix_exchange_messages(list, mail) if mail.header_fields.any?{|f| f.name =~ /^X-MS-Exchange-/i } && !mail[:content_type].blank? && mail[:content_type].content_type == 'multipart/mixed' && mail.parts.size > 2 && mail.parts[0][:content_type].content_type == 'text/plain' && mail.parts[0].body.to_s.blank? && mail.parts[1][:content_type].content_type == 'application/pgp-encrypted' && mail.parts[2][:content_type].content_type == 'application/octet-stream' mail.parts.delete_at(0) mail.content_type = [:multipart, :encrypted, {protocol: "application/pgp-encrypted", boundary: mail.boundary}] end end end end schleuder-3.6.0/lib/schleuder/filters/pre_decryption/50_strip_html_from_alternative.rb000066400000000000000000000011561401002544500313550ustar00rootroot00000000000000module Schleuder module Filters def self.strip_html_from_alternative(list, mail) if mail[:content_type].blank? || mail[:content_type].content_type != 'multipart/alternative' || ! mail.to_s.include?('BEGIN PGP ') return false end Schleuder.logger.debug "Stripping html-part from multipart/alternative-message" mail.parts.delete_if do |part| part[:content_type].content_type == 'text/html' end mail.content_type = 'multipart/mixed' mail.add_pseudoheader(:note, I18n.t("pseudoheaders.stripped_html_from_multialt")) end end end schleuder-3.6.0/lib/schleuder/filters_runner.rb000066400000000000000000000051021401002544500216010ustar00rootroot00000000000000module Schleuder module Filters class Runner attr_reader :list, :filter_type def initialize(list, filter_type) @list = list @filter_type = filter_type end def run(mail) filters.map do |cmd| list.logger.debug "Calling filter #{cmd}" response = Filters.send(cmd, list, mail) if stop?(response) if bounce?(response, mail) return response else return nil end end end nil end def filters @filters ||= load_filters end private def stop?(response) response.kind_of?(StandardError) end def bounce?(response, mail) if list.bounces_drop_all list.logger.debug "Dropping bounce as configurated" notify_admins(I18n.t('.bounces_drop_all'), mail.original_message) return false end list.bounces_drop_on_headers.each do |key, value| if mail[key].to_s.match(/#{value}/i) list.logger.debug "Incoming message header key '#{key}' matches value '#{value}': dropping the bounce." notify_admins(I18n.t('.bounces_drop_on_headers', key: key, value: value), mail.original_message) return false end end list.logger.debug "Bouncing message" true end def notify_admins(reason, original_message) if list.bounces_notify_admins? list.logger.notify_admin reason, original_message, I18n.t('notice') end end def load_filters list.logger.debug "Loading #{filter_type}_decryption filters" sorted_filters.map do |filter_name| require all_filter_files[filter_name] filter_name.split('_',2).last end end def sorted_filters @sorted_filters ||= all_filter_files.keys.sort do |a,b| a.split('_',2).first.to_i <=> b.split('_',2).first.to_i end end def all_filter_files @all_filter_files ||= begin files_in_filter_dirs = Dir[*filter_dirs] files_in_filter_dirs.inject({}) do |res,file| filter_name = File.basename(file,'.rb') res[filter_name] = file res end end end def filter_dirs @filter_dirs ||= [File.join(File.dirname(__FILE__),"filters"), Schleuder::Conf.filters_dir].map do |d| File.join(d,"#{filter_type}_decryption/[0-9]*_*.rb") end end end end end schleuder-3.6.0/lib/schleuder/gpgme/000077500000000000000000000000001401002544500173145ustar00rootroot00000000000000schleuder-3.6.0/lib/schleuder/gpgme/ctx.rb000066400000000000000000000224471401002544500204500ustar00rootroot00000000000000module GPGME class Ctx IMPORT_FLAGS = { 'new_key' => 1, 'new_uids' => 2, 'new_signatures' => 4, 'new_subkeys' => 8 } def keyimport(keydata) self.import_keys(GPGME::Data.new(keydata)) result = self.import_result result.imports.map(&:set_action) result end # TODO: find solution for I18n — could be a different language in API-clients than here! def interpret_import_result(import_result) case import_result.imports.size when 1 import_status = import_result.imports.first if import_status.action == 'error' [nil, "Key #{import_status.fpr} could not be imported!"] else [import_status.fpr, nil] end when 0 [nil, "The given key material did not contain any keys!"] else # TODO: report import-stati of the keys? [nil, "The given key material contained more than one key, could not determine which fingerprint to use. Please set it manually!"] end end def find_keys(input=nil, secret_only=nil) _, input = clean_and_classify_input(input) keys(input, secret_only) end def find_distinct_key(input=nil, secret_only=nil) _, input = clean_and_classify_input(input) keys = keys(input, secret_only) if keys.size == 1 keys.first else nil end end def clean_and_classify_input(input) case input when /.*?([^ <>]+@[^ <>]+).*?/ [:email, "<#{$1}>"] when /^http/ [:url, input] when Conf::FINGERPRINT_REGEXP [:fingerprint, "0x#{input.gsub(/^0x/, '')}"] else [nil, input] end end # Tell gpgme to use the given binary. def self.set_gpg_path_from_env path = ENV['GPGBIN'].to_s if ! path.empty? Schleuder.logger.debug "setting gpg to use #{path}" GPGME::Engine.set_info(GPGME::PROTOCOL_OpenPGP, path, ENV['GNUPGHOME']) if gpg_engine.version.nil? $stderr.puts "Error: The binary you specified doesn't provide a gpg-version." exit 1 end end end def self.sufficient_gpg_version?(required) Gem::Version.new(required) <= Gem::Version.new(gpg_engine.version) end def self.check_gpg_version if ! sufficient_gpg_version?('2.0') $stderr.puts "Error: GnuPG version >= 2.0 required.\nPlease install it and/or provide the path to the binary via the environment-variable GPGBIN.\nExample: GPGBIN=/opt/gpg2/bin/gpg ..." exit 1 end end def self.gpg_engine GPGME::Engine.info.find {|e| e.protocol == GPGME::PROTOCOL_OpenPGP } end def refresh_keys(keys) # reorder keys so the update pattern is random output = keys.shuffle.map do |key| # Sleep a short while to make traffic analysis less easy. sleep rand(1.0..5.0) refresh_key(key.fingerprint).presence end # TODO: drop version check once we killed gpg 2.0 support. if GPGME::Ctx.sufficient_gpg_version?('2.1') `gpgconf --kill dirmngr` end output.compact.join("\n") end def refresh_key(fingerprint) args = "#{keyserver_arg} #{import_filter_arg} --refresh-keys #{fingerprint}" gpgerr, gpgout, exitcode = self.class.gpgcli(args) if exitcode > 0 # Return filtered error messages. Include gpgkeys-messages from stdout # (gpg 2.0 does that), which could e.g. report a failure to connect to # the keyserver. res = [ refresh_key_filter_messages(gpgerr), refresh_key_filter_messages(gpgout).grep(/^gpgkeys: /) ].flatten.compact # if there was an error that we don't filter out, # we better kill dirmngr, so it hopefully won't suffer # from the same error during the next run. # See #309 for background # TODO: drop version check once we killed gpg 2.0 support. if !res.empty? && GPGME::Ctx.sufficient_gpg_version?('2.1') `gpgconf --kill dirmngr` end res.join("\n") else lines = translate_output('key_updated', gpgout).reject do |line| # Reduce the noise a little. line.match(/.* \(unchanged\):$/) end lines.join("\n") end end def fetch_key(input) arguments, error = fetch_key_gpg_arguments_for(input) return error if error self.class.send_notice_if_gpg_does_not_know_import_filter gpgerr, gpgout, exitcode = self.class.gpgcli("#{import_filter_arg} #{arguments}") # Unfortunately gpg doesn't exit with code > 0 if `--fetch-key` fails. if exitcode > 0 || gpgerr.grep(/ unable to fetch /).presence "Fetching #{input} did not succeed:\n#{gpgerr.join("\n")}" else translate_output('key_fetched', gpgout).join("\n") end end def fetch_key_gpg_arguments_for(input) case input when Conf::FINGERPRINT_REGEXP "#{keyserver_arg} --recv-key #{input}" when /^http/ "--fetch-key #{input}" when /@/ # --recv-key doesn't work with email-addresses, so we use --locate-key # restricted to keyservers. "#{keyserver_arg} --auto-key-locate keyserver --locate-key #{input}" else [nil, I18n.t("fetch_key.invalid_input")] end end def translate_output(locale_key, gpgoutput) import_states = translate_import_data(gpgoutput) strings = import_states.map do |fingerprint, states| key = find_distinct_key(fingerprint) I18n.t(locale_key, { key_oneline: key.oneline, states: states.to_sentence }) end strings end def translate_import_data(gpgoutput) result = {} gpgoutput.grep(/IMPORT_OK/) do |import_ok| next if import_ok.blank? import_status, fingerprint = import_ok.split(/\s/).slice(2, 2) import_status = import_status.to_i states = [] if import_status == 0 states << I18n.t("import_states.unchanged") else IMPORT_FLAGS.each do |text, int| if (import_status & int) > 0 states << I18n.t("import_states.#{text}") end end end result[fingerprint] = states end result end # Unfortunately we can't distinguish between a failure to connect the # keyserver, and a failure to find the key on the server. So we try to # filter misleading errors to check if there are any to be reported. def refresh_key_filter_messages(strings) strings.reject do |line| line.chomp == 'gpg: keyserver refresh failed: No data' || line.match(/^gpgkeys: key .* not found on keyserver/) || line.match(/^gpg: refreshing /) || line.match(/^gpg: requesting key /) || line.match(/^gpg: no valid OpenPGP data found/) end end def self.gpgcli(args) exitcode = -1 errors = [] output = [] base_cmd = gpg_engine.file_name base_args = "--no-greeting --no-permission-warning --quiet --armor --trust-model always --no-tty --command-fd 0 --status-fd 1" cmd = [base_cmd, base_args, args].flatten.join(' ') Open3.popen3(cmd) do |stdin, stdout, stderr, thread| if block_given? output = yield(stdin, stdout, stderr) else output = stdout.readlines end stdin.close if ! stdin.closed? errors = stderr.readlines exitcode = thread.value.exitstatus end [errors, output, exitcode] rescue Errno::ENOENT raise 'Need gpg in $PATH or in $GPGBIN' end def self.gpgcli_expect(args) gpgcli(args) do |stdin, stdout, stderr| counter = 0 while line = stdout.gets rescue nil counter += 1 if counter > 1042 return "Too many input-lines from gpg, something went wrong" end output, error = yield(line.chomp) if output == false return error elsif output stdin.puts output end end end end def self.spawn_daemon(name, args) delete_daemon_socket(name) cmd = "#{name} #{args} --daemon > /dev/null 2>&1" if ! system(cmd) return [false, "#{name} exited with code #{$?}"] end end def self.delete_daemon_socket(name) path = File.join(ENV["GNUPGHOME"], "S.#{name}") if File.exist?(path) File.delete(path) end end def keyserver_arg if Conf.keyserver.present? "--keyserver #{Conf.keyserver}" else "" end end def self.gpg_knows_import_filter? sufficient_gpg_version?('2.1.15') end def import_filter_arg if self.class.gpg_knows_import_filter? %{ --import-filter drop-sig='sig_created_d > 0000-00-00'} end end def self.send_notice_if_gpg_does_not_know_import_filter if ! gpg_knows_import_filter? Schleuder.logger.notify_superadmin( subject: 'Schleuder installation problem', message: "Your version of GnuPG is very old, please update!\n\nWith your version of GnuPG we can not protect your setup against signature flooding. Please update to at least version 2.1.15 to fix this problem. See for details on the background." ) '' end end end end schleuder-3.6.0/lib/schleuder/gpgme/import_status.rb000066400000000000000000000017601401002544500225620ustar00rootroot00000000000000module GPGME class ImportStatus attr_reader :action # Unfortunately in initialize() @status and @result are not yet initialized. def set_action @action ||= if self.result > 0 # An error happened. # TODO: Give details by going through the list of errors in # "gpg-errors.h" and find out which is present here. 'error' else # TODO: refactor with Ctx#translate_import_data case self.status when 0 'unchanged' when IMPORT_NEW 'imported' else 'updated' end end self end # Force encoding, some databases save "ASCII-8BIT" as binary data. alias_method :orig_fingerprint, :fingerprint def fingerprint orig_fingerprint.encode(Encoding::US_ASCII) end end end schleuder-3.6.0/lib/schleuder/gpgme/key.rb000066400000000000000000000137261401002544500204420ustar00rootroot00000000000000module GPGME class Key # Overwrite to specify the full fingerprint instead of the short key-ID. def to_s primary_subkey = subkeys[0] s = sprintf("%s %4d%s/%s %s\n", primary_subkey.secret? ? 'sec' : 'pub', primary_subkey.length, primary_subkey.pubkey_algo_letter, primary_subkey.fingerprint, primary_subkey.timestamp.strftime('%Y-%m-%d')) uids.each do |user_id| s << "uid\t\t#{user_id.name} <#{user_id.email}>\n" end subkeys.each do |subkey| s << subkey.to_s end s end def generated_at primary_subkey.timestamp end def expired? expired.present? end def oneline @oneline ||= begin datefmt = '%Y-%m-%d' attribs = [ "0x#{fingerprint}", email, generated_at.strftime(datefmt) ] if usability_issue.present? case usability_issue when :expired attribs << "[expired: #{expires.strftime(datefmt)}]" when :revoked # TODO: add revocation date when it's available. attribs << "[revoked]" else attribs << "[#{usability_issue}]" end end if expires? && ! expired? attribs << "[expires: #{expires.strftime(datefmt)}]" end attribs.join(' ') end end def armored "#{self.to_s}\n\n#{export(armor: true).read}" end def minimal export(minimal: true).to_s end # Force encoding, some databases save "ASCII-8BIT" as binary data. alias_method :orig_fingerprint, :fingerprint def fingerprint orig_fingerprint.encode(Encoding::US_ASCII) end def usable? usability_issue.blank? end def usability_issue if trust.present? trust elsif ! usable_for?(:encrypt) "not capable of encryption" else nil end end def set_primary_uid(email) # We rely on the order of UIDs here. Seems to work. index = self.uids.map(&:email).index(email) uid_number = index + 1 primary_set = false args = "--edit-key '#{self.fingerprint}' #{uid_number}" errors, _ = GPGME::Ctx.gpgcli_expect(args) do |line| case line.chomp when /keyedit.prompt/ if ! primary_set primary_set = true "primary" else "save" end else nil end end errors.join end def adduid(uid, email) # This block can be deleted once we cease to support gnupg 2.0. if ! GPGME::Ctx.sufficient_gpg_version?('2.1.4') return adduid_expect(uid, email) end # Specifying the key via fingerprint apparently doesn't work. errors, _ = GPGME::Ctx.gpgcli("--quick-adduid #{uid} '#{uid} <#{email}>'") errors.join end # This method can be deleted once we cease to support gnupg 2.0. def adduid_expect(uid, email) args = "--allow-freeform-uid --edit-key '#{self.fingerprint}' adduid" errors, _ = GPGME::Ctx.gpgcli_expect(args) do |line| case line.chomp when /keygen.name/ uid when /keygen.email/ email when /keygen.comment/ '' when /keyedit.prompt/ "save" else nil end end errors.join end def clearpassphrase(oldpw) # This block can be deleted once we cease to support gnupg 2.0. if ! GPGME::Ctx.sufficient_gpg_version?('2.1.0') return clearpassphrase_v20(oldpw) end oldpw_given = false # Don't use '--passwd', it claims to fail (even though it factually doesn't). args = "--pinentry-mode loopback --edit-key '#{self.fingerprint}' passwd" errors, _, exitcode = GPGME::Ctx.gpgcli_expect(args) do |line| case line when /passphrase.enter/ if ! oldpw_given oldpw_given = true oldpw else "" end when /BAD_PASSPHRASE/ [false, 'bad passphrase'] when /change_passwd.empty.okay/ 'y' when /keyedit.prompt/ "save" else nil end end # Only show errors if something apparently went wrong. Otherwise we might # leak useless strings from gpg and make the caller report errors even # though this method succeeded. if exitcode > 0 errors.join else nil end end # This method can be deleted once we cease to support gnupg 2.0. def clearpassphrase_v20(oldpw) start_gpg_agent(oldpw) # Don't use '--passwd', it claims to fail (even though it factually doesn't). errors, _, exitcode = GPGME::Ctx.gpgcli_expect("--edit-key '#{self.fingerprint}' passwd") do |line| case line when /BAD_PASSPHRASE/ [false, 'bad passphrase'] when /change_passwd.empty.okay/ 'y' when /keyedit.prompt/ "save" else nil end end stop_gpg_agent # Only show errors if something apparently went wrong. Otherwise we might # leak useless strings from gpg and make the caller report errors even # though this method succeeded. if exitcode > 0 errors.join else nil end end # This method can be deleted once we cease to support gnupg 2.0. def stop_gpg_agent # gpg-agent terminates itself if its socket goes away. GPGME::Ctx.delete_daemon_socket('gpg-agent') end def start_gpg_agent(oldpw) ENV['PINENTRY_USER_DATA'] = oldpw pinentry = File.join(ENV['SCHLEUDER_ROOT'], 'bin', 'pinentry-clearpassphrase') GPGME::Ctx.spawn_daemon('gpg-agent', "--use-standard-socket --pinentry-program #{pinentry}") end def self.valid_fingerprint?(fp) fp =~ Schleuder::Conf::FINGERPRINT_REGEXP end end end schleuder-3.6.0/lib/schleuder/gpgme/sub_key.rb000066400000000000000000000005241401002544500213030ustar00rootroot00000000000000module GPGME class SubKey # Overwrite to specify the full fingerprint instead of the short key-ID. def to_s sprintf("%s %4d%s/%s %s\n", secret? ? 'ssc' : 'sub', length, pubkey_algo_letter, fingerprint, timestamp.strftime('%Y-%m-%d')) end end end schleuder-3.6.0/lib/schleuder/gpgme/user_id.rb000066400000000000000000000006461401002544500213010ustar00rootroot00000000000000module GPGME class UserID def name sanitize_encoding(@name) end def comment sanitize_encoding(@comment) end def uid sanitize_encoding(@uid) end private def sanitize_encoding(str) if str.is_a?(String) && str.encoding != 'UTF-8' str.encode(Encoding::UTF_8, invalid: :replace, undef: :replace, replace: '') else str end end end end schleuder-3.6.0/lib/schleuder/list.rb000066400000000000000000000274401401002544500175240ustar00rootroot00000000000000module Schleuder class List < ActiveRecord::Base has_many :subscriptions, dependent: :destroy before_destroy :delete_listdirs serialize :headers_to_meta, JSON serialize :bounces_drop_on_headers, JSON serialize :keywords_admin_only, JSON serialize :keywords_admin_notify, JSON validates :email, presence: true, uniqueness: true, email: true validates :fingerprint, presence: true, fingerprint: true validates :send_encrypted_only, :receive_encrypted_only, :receive_signed_only, :receive_authenticated_only, :receive_from_subscribed_emailaddresses_only, :receive_admin_only, :keep_msgid, :bounces_drop_all, :deliver_selfsent, :bounces_notify_admins, :include_list_headers, :include_openpgp_header, :forward_all_incoming_to_admins, boolean: true validates_each :headers_to_meta, :keywords_admin_only, :keywords_admin_notify do |record, attrib, value| value.each do |word| if word !~ /\A[a-z_-]+\z/i record.errors.add(attrib, I18n.t("errors.invalid_characters")) end end end validates_each :bounces_drop_on_headers do |record, attrib, value| value.each do |key, val| if key.to_s !~ /\A[a-z-]+\z/i || val.to_s !~ /\A[[:graph:]]+\z/i record.errors.add(attrib, I18n.t("errors.invalid_characters")) end end end validates :subject_prefix, :subject_prefix_in, :subject_prefix_out, no_line_breaks: true validates :openpgp_header_preference, presence: true, inclusion: { in: %w(sign encrypt signencrypt unprotected none), } validates :max_message_size_kb, :logfiles_to_keep, greater_than_zero: true validates :log_level, presence: true, inclusion: { in: %w(debug info warn error), } validates :language, presence: true, inclusion: { # TODO: find out why we break translations and available_locales if we use I18n.available_locales here. in: %w(de en), } validates :public_footer, :internal_footer, allow_blank: true, format: { with: /\A[[:graph:]\s]*\z/i, } # Some users find it quite confusing when they click "reply-to" and the mail client # doesn't reply to the sender of the mail but the whole mailing list. For those lists it can be # considered to set this value to true. The recipients will then receive e-mails # where the "reply-to" header will contain the reply-to address # of the sender and thus reply to the sender when clicking "reply-to" in a client. # If no "reply-to" is set, the "from"-header of the original sender will be used. # The default is off. validates :set_reply_to_to_sender, boolean: true # Some users find it confusing when the "from" does not contain the original sender # but the list address. For those lists it can be considered to set the munged header. # This will result in a "from"-header like this: "originalsender@original.com via list@list.com" # The default is off. validates :munge_from, boolean: true default_scope { order(:email) } def self.configurable_attributes @configurable_attributes ||= begin all = self.validators.map(&:attributes).flatten.uniq.compact.sort all - [:email, :fingerprint] end end def logfile @logfile ||= File.join(Conf.listlogs_dir, self.email.split('@').reverse, 'list.log') end def logger @logger ||= Listlogger.new(self) end def to_s email end def admins subscriptions.where(admin: true) end def subscriptions_without_fingerprint subscriptions.without_fingerprint end def key(fingerprint=self.fingerprint) keys(fingerprint).first end def secret_key keys(self.fingerprint, true).first end def keys(identifier=nil, secret_only=nil) gpg.find_keys(identifier, secret_only) end # TODO: find better name for this method. It does more than the current # name suggests (filtering for capability). def distinct_key(identifier) keys = keys(identifier).select { |key| key.usable_for?(:encrypt) } if keys.size == 1 return keys.first else return nil end end def import_key(importable) gpg.keyimport(importable) end def import_key_and_find_fingerprint(key_material) return nil if key_material.blank? import_result = import_key(key_material) gpg.interpret_import_result(import_result) end def delete_key(fingerprint) if key = keys(fingerprint).first key.delete! true else false end end def export_key(fingerprint=self.fingerprint) key = keys(fingerprint).first if key.blank? return false end key.armored end def key_minimal_base64_encoded(fingerprint=self.fingerprint) key = keys(fingerprint).first if key.blank? return false end Base64.strict_encode64(key.minimal) end def check_keys now = Time.now checkdate = now + (60 * 60 * 24 * 14) # two weeks unusable = [] expiring = [] keys.each do |key| expiry = key.subkeys.first.expires if expiry && expiry > now && expiry < checkdate # key expires in the near future expdays = ((expiry - now)/86400).to_i expiring << [key, expdays] end if ! key.usable? unusable << [key, key.usability_issue] end end text = '' expiring.each do |key,days| text << I18n.t('key_expires', { days: days, key_oneline: key.oneline }) text << "\n" end unusable.each do |key,usability_issue| text << I18n.t('key_unusable', { usability_issue: usability_issue, key_oneline: key.oneline }) text << "\n" end text end def refresh_keys gpg.refresh_keys(self.keys) end def fetch_keys(input) gpg.fetch_key(input) end def pin_keys updated_emails = subscriptions_without_fingerprint.collect do |subscription| key = distinct_key(subscription.email) if key subscription.update(fingerprint: key.fingerprint) "#{subscription.email}: #{key.fingerprint}" else nil end end updated_emails.compact.join("\n") end def self.by_recipient(recipient) listname = recipient.gsub(/-(sendkey|request|owner|bounce)@/, '@') where(email: listname).first end def sendkey_address @sendkey_address ||= email.gsub('@', '-sendkey@') end def request_address @request_address ||= email.gsub('@', '-request@') end def owner_address @owner_address ||= email.gsub('@', '-owner@') end def bounce_address @bounce_address ||= email.gsub('@', '-bounce@') end def gpg @gpg_ctx ||= begin # TODO: figure out why set it again... # Set GNUPGHOME when list is created. set_gnupg_home GPGME::Ctx.new armor: true end end # TODO: place this somewhere sensible. # Call cleanup when script finishes. #Signal.trap(0, proc { @list.cleanup }) def cleanup if @gpg_agent_pid Process.kill('TERM', @gpg_agent_pid.to_i) end rescue => e $stderr.puts "Failed to kill gpg-agent: #{e}" end def gpg_sign_options {sign: true, sign_as: self.fingerprint} end def fingerprint=(arg) if arg write_attribute(:fingerprint, arg.gsub(/\s*/, '').gsub(/^0x/, '').chomp.upcase) end end def self.listdir(listname) File.join( Conf.lists_dir, listname.split('@').reverse ) end def listdir @listdir ||= self.class.listdir(self.email) end # A convenience-method to simplify other code. def subscribe(email, fingerprint=nil, adminflag=nil, deliveryflag=nil, key_material=nil) messages = nil args = { list_id: self.id, email: email } if key_material.present? fingerprint, messages = import_key_and_find_fingerprint(key_material) end args[:fingerprint] = fingerprint # ActiveRecord does not treat nil as falsy for boolean columns, so we # have to avoid that in order to not receive an invalid object. The # database will use the column's default-value if no value is being # given. (I'd rather not duplicate the defaults here.) if ! adminflag.nil? args[:admin] = adminflag end if ! deliveryflag.nil? args[:delivery_enabled] = deliveryflag end subscription = Subscription.create(args) [subscription, messages] end def unsubscribe(email, delete_key=false) sub = subscriptions.where(email: email).first if sub.blank? false end if ! sub.destroy return sub end if delete_key sub.delete_key end end def keywords_admin_notify Array(read_attribute(:keywords_admin_notify)) end def keywords_admin_only Array(read_attribute(:keywords_admin_only)) end def admin_only?(keyword) keywords_admin_only.include?(keyword) end def from_admin?(mail) return false if ! mail.was_validly_signed? admins.find do |admin| admin.fingerprint == mail.signing_key.fingerprint end.presence || false end def set_attribute(attrib, value) self.send("#{attrib}=", value) end def send_list_key_to_subscriptions mail = Mail.new mail.from = self.email mail.subject = I18n.t('list_public_key_subject') mail.body = I18n.t('list_public_key_attached') mail.attach_list_key!(self) send_to_subscriptions(mail) true end def send_to_subscriptions(mail, incoming_mail=nil) logger.debug "Sending to subscriptions." mail.add_internal_footer! self.subscriptions.each do |subscription| begin if ! subscription.delivery_enabled logger.info "Not sending to #{subscription.email}: delivery is disabled." next end if ! self.deliver_selfsent && incoming_mail.was_validly_signed? && ( subscription == incoming_mail.signer ) logger.info "Not sending to #{subscription.email}: delivery of self sent is disabled." next end subscription.send_mail(mail, incoming_mail) rescue => exc msg = I18n.t('errors.delivery_error', { email: subscription.email, error: exc.to_s }) logger.error msg logger.error exc end end end private def set_gnupg_home ENV['GNUPGHOME'] = listdir end def delete_listdirs if File.exists?(self.listdir) FileUtils.rm_rf(self.listdir, secure: true) Schleuder.logger.info "Deleted #{self.listdir}" end # If listlogs_dir is different from lists_dir, the logfile still exists # and needs to be deleted, too. logfile_dir = File.dirname(self.logfile) if File.exists?(logfile_dir) FileUtils.rm_rf(logfile_dir, secure: true) Schleuder.logger.info "Deleted #{logfile_dir}" end true rescue => exc # Don't use list-logger here — if the list-dir isn't present we can't log to it! Schleuder.logger.error "Error while deleting listdir: #{exc}" return false end end end schleuder-3.6.0/lib/schleuder/list_builder.rb000066400000000000000000000071441401002544500212310ustar00rootroot00000000000000module Schleuder class ListBuilder def initialize(list_attributes, adminemail=nil, adminfingerprint=nil, adminkey=nil) @list_attributes = list_attributes.with_indifferent_access @listname = list_attributes[:email] @fingerprint = list_attributes[:fingerprint] @adminemail = adminemail @adminfingerprint = adminfingerprint @adminkey = adminkey end def read_default_settings hash = YAML.load_file(ENV['SCHLEUDER_LIST_DEFAULTS']) if ! hash.kind_of?(Hash) raise Errors::LoadingListSettingsFailed.new end hash rescue Psych::SyntaxError raise Errors::LoadingListSettingsFailed.new end def run Schleuder.logger.info "Building new list" if @listname.blank? || ! @listname.match(Conf::EMAIL_REGEXP) return [nil, {'email' => ["'#{@listname}' is not a valid email address"]}] end settings = read_default_settings.merge(@list_attributes) list = List.new(settings) @list_dir = list.listdir create_or_test_dir(@list_dir) # In case listlogs_dir != lists_dir we have to create the basedir of the # list's log-file. create_or_test_dir(File.dirname(list.logfile)) if list.fingerprint.blank? list_key = gpg.keys("<#{list.email}>").first if list_key.nil? list_key = create_key(list) end list.fingerprint = list_key.fingerprint end if ! list.valid? return list end list.save! if @adminemail.blank? msg = nil else sub, msg = list.subscribe(@adminemail, @adminfingerprint, true, true, @adminkey) if sub.errors.present? raise Errors::ActiveModelError.new(sub.errors) end end [list, msg] end def gpg @gpg_ctx ||= begin ENV["GNUPGHOME"] = @list_dir GPGME::Ctx.new end end def create_key(list) Schleuder.logger.info "Generating key-pair, this could take a while..." gpg.generate_key(key_params(list)) # Get key without knowing the fingerprint yet. keys = list.keys(@listname) if keys.empty? raise Errors::KeyGenerationFailed.new(@list_dir, @listname) elsif keys.size > 1 raise Errors::TooManyKeys.new(@list_dir, @listname) else adduids(list, keys.first) end keys.first end def adduids(list, key) # Add UIDs for -owner and -request. [list.request_address, list.owner_address].each do |address| err = key.adduid(list.email, address) if err.present? raise err end end # Go through list.key() to re-fetch the key from the keyring, otherwise # we don't see the new UIDs. errors = list.key.set_primary_uid(list.email) if errors.present? raise errors end rescue => exc raise Errors::KeyAdduidFailed.new(exc.to_s) end def key_params(list) " Key-Type: RSA Key-Length: 4096 Key-Usage: sign Subkey-Type: RSA Subkey-Length: 4096 Subkey-Usage: encrypt Name-Real: #{list.email} Name-Email: #{list.email} Expire-Date: 0 %no-protection " end def create_or_test_dir(dir) if File.exists?(dir) if ! File.directory?(dir) raise Errors::ListdirProblem.new(dir, :not_a_directory) end if ! File.writable?(dir) raise Errors::ListdirProblem.new(dir, :not_writable) end else FileUtils.mkdir_p(dir) end end end end schleuder-3.6.0/lib/schleuder/listlogger.rb000066400000000000000000000017261401002544500207230ustar00rootroot00000000000000module Schleuder class Listlogger < ::Logger include LoggerNotifications def initialize(list) super(list.logfile, 'daily') @from = list.email @list = list @adminaddresses = list.admins.map { |sub| [sub.email, sub.key] } @level = ::Logger.const_get(list.log_level.upcase) remove_old_logfiles(list) end # Logger rotates but doesn't delete older files, so we're helping # ourselves. def remove_old_logfiles(list) logfiles_to_keep = list.logfiles_to_keep.to_i if logfiles_to_keep < 1 logfiles_to_keep = list.class.column_defaults['logfiles_to_keep'] end suffix_now = Time.now.strftime("%Y%m%d").to_i del_older_than = suffix_now - logfiles_to_keep Pathname.glob("#{list.logfile}.????????").each do |file| if file.basename.to_s.match(/\.([0-9]{8})$/) if del_older_than.to_i >= $1.to_i file.unlink end end end end end end schleuder-3.6.0/lib/schleuder/logger.rb000066400000000000000000000010411401002544500200150ustar00rootroot00000000000000module Schleuder def logger @logger ||= Logger.new end module_function :logger class Logger < Syslog::Logger include LoggerNotifications def initialize if RUBY_VERSION.to_f < 2.1 super('Schleuder') else super('Schleuder', Syslog::LOG_MAIL) end # We need some sender-address different from the superadmin-address. @from = "#{`whoami`.chomp}@#{`hostname`.chomp}" @adminaddresses = Conf.superadmin @level = ::Logger.const_get(Conf.log_level.upcase) end end end schleuder-3.6.0/lib/schleuder/logger_notifications.rb000066400000000000000000000041361401002544500227560ustar00rootroot00000000000000module Schleuder module LoggerNotifications def adminaddresses @adminaddresses.presence || superadmin end def superadmin Conf.superadmin.presence end def error(string) super(string) notify_admin(string) end def fatal(string, original_message=nil) super(string.to_s + append_original_message(original_message)) notify_admin(string, original_message) end def notify_superadmin(message:, original_message: nil, subject: 'Error') notify_admin(message, original_message, subject, superadmin) end def notify_admin(thing, original_message=nil, subject='Error', recipients=nil) # Minimize using other classes here, we don't know what caused the error. msg_parts = convert_to_msg_parts(thing, original_message) recipients ||= adminaddresses Array(adminaddresses).each do |address, key| mail = Mail.new mail.from = @from mail.to = address mail.subject = subject mail[:Errors_To] = superadmin mail.sender = superadmin msg_parts.each do |msg_part| mail.add_part(msg_part) end if @list.present? gpg_opts = @list.gpg_sign_options if key.present? && key.usable? gpg_opts.merge!(encrypt: true, keys: { address => key.fingerprint }) end mail.gpg gpg_opts mail.header['List-Id'] = "<#{@list.email.gsub('@', '.')}>" end mail.deliver end true end private def convert_to_msg_parts(thing, original_message) msg_parts = Mail::Message.all_to_message_part(thing) if original_message.present? orig_part = Mail::Part.new orig_part.content_type = 'message/rfc822' orig_part.content_description = 'The originally incoming message' orig_part.body = original_message.to_s msg_parts << orig_part end msg_parts end def append_original_message(original_message) if original_message "\n\nOriginal message:\n\n#{original_message.to_s}" else '' end end end end schleuder-3.6.0/lib/schleuder/mail/000077500000000000000000000000001401002544500171375ustar00rootroot00000000000000schleuder-3.6.0/lib/schleuder/mail/encrypted_part.rb000066400000000000000000000015241401002544500225110ustar00rootroot00000000000000module Mail module Gpg class EncryptedPart < Mail::Part alias_method :initialize_mailgpg, :initialize def initialize(cleartext_mail, options = {}) if cleartext_mail.protected_headers_subject cleartext_mail.content_type_parameters['protected-headers'] = 'v1' end initialize_mailgpg(cleartext_mail, options) end end end end schleuder-3.6.0/lib/schleuder/mail/gpg.rb000066400000000000000000000006151401002544500202430ustar00rootroot00000000000000module Mail module Gpg class << self alias_method :encrypt_mailgpg, :encrypt def encrypt(cleartext_mail, options={}) encrypted_mail = encrypt_mailgpg(cleartext_mail, options) if cleartext_mail.protected_headers_subject encrypted_mail.subject = cleartext_mail.protected_headers_subject end encrypted_mail end end end end schleuder-3.6.0/lib/schleuder/mail/message.rb000066400000000000000000000521571401002544500211220ustar00rootroot00000000000000module Mail # creates a Mail::Message likes schleuder def self.create_message_to_list(msg, recipient, list) mail = Mail.new(msg) mail.list = list mail.recipient = recipient # don't freeze here, as the mail might not be fully # parsed as body is lazy evaluated and might still # be changed later. mail.original_message = mail.dup #.freeze mail end # TODO: Test if subclassing breaks integration of mail-gpg. class Message attr_accessor :recipient attr_accessor :original_message attr_accessor :list attr_accessor :protected_headers_subject attr_writer :dynamic_pseudoheaders # TODO: This should be in initialize(), but I couldn't understand the # strange errors about wrong number of arguments when overriding # Message#initialize. def setup if self.encrypted? new = self.decrypt(verify: true) # Test if there's a signed multipart inside the ciphertext # ("encapsulated" format of pgp/mime). if encapsulated_signed?(new) new = new.verify end elsif self.signed? new = self.verify else new = self end new.list = self.list new.recipient = self.recipient new.gpg list.gpg_sign_options new.original_message = self.dup.freeze # Trigger method early to save the information. Later some information # might be gone (e.g. request-keywords that delete subscriptions or # keys). new.signer new.dynamic_pseudoheaders = self.dynamic_pseudoheaders.dup # Store previously protected subject for later access. # mail-gpg pulls headers from the decrypted mime parts "up" into the main # headers, which reveals protected subjects. if self.subject != new.subject new.protected_headers_subject = self.subject.dup end # Delete the protected headers which might leak information. if new.parts.first && new.parts.first.content_type == "text/rfc822-headers; protected-headers=v1" new.parts.shift end new end def clean_copy(with_pseudoheaders=false) clean = Mail.new clean.list = self.list clean.gpg self.list.gpg_sign_options clean.from = list.email clean.subject = self.subject clean.protected_headers_subject = self.protected_headers_subject clean.add_msgids(list, self) clean.add_list_headers(list) clean.add_openpgp_headers(list) if with_pseudoheaders new_part = Mail::Part.new new_part.body = self.pseudoheaders(list) clean.add_part new_part end if self.protected_headers_subject.present? new_part = Mail::Part.new new_part.content_type = "text/rfc822-headers; protected-headers=v1" new_part.body = "Subject: #{self.subject}\n" clean.add_part new_part end # Attach body or mime-parts in a new wrapper-part, to preserve the # original mime-structure. # We can't use self.to_s here — that includes all the headers we *don't* # want to copy. wrapper_part = Mail::Part.new # Copy headers to are relevant for the mime-structure. wrapper_part.content_type = self.content_type wrapper_part.content_transfer_encoding = self.content_transfer_encoding if self.content_transfer_encoding wrapper_part.content_disposition = self.content_disposition if self.content_disposition wrapper_part.content_description = self.content_description if self.content_description # Copy contents. if self.multipart? self.parts.each do |part| wrapper_part.add_part(part) end else # We copied the content-headers, so we need to copy the body encoded. # Otherwise the content might become unlegible. wrapper_part.body = self.body.encoded end clean.add_part(wrapper_part) clean end def prepend_part(part) self.add_part(part) self.parts.unshift(parts.delete_at(parts.size-1)) end def add_public_footer! # Add public_footer unless it's empty?. add_footer!(:public_footer) end def add_internal_footer! add_footer!(:internal_footer) end def was_encrypted? Mail::Gpg.encrypted?(original_message) end def signature case signatures.size when 0 if multipart? signature_multipart_inline else nil end when 1 signatures.first else raise "Multiple signatures found! Cannot handle!" end end def was_validly_signed? signature.present? && signature.valid? && signer.present? end def signer @signer ||= begin if signing_key.present? list.subscriptions.where(fingerprint: signing_key.fingerprint).first end end end # The fingerprint of the signature might be the one of a sub-key, but the # subscription-assigned fingerprints are (should be) the ones of the # primary keys, so we need to look up the key. def signing_key if signature.present? @signing_key ||= list.keys(signature.fpr).first end end def reply_to_signer(output) reply = self.reply self.class.all_to_message_part(output).each do |part| reply.add_part(part) end self.signer.send_mail(reply) end def self.all_to_message_part(input) Array(input).map do |thing| case thing when Mail::Part thing when String, StandardError Mail::Part.new do body thing.to_s end else raise "Don't know how to handle input: #{thing.inspect}" end end end def sendkey_request? @recipient.match(/-sendkey@/) end def to_owner? @recipient.match(/-owner@/) end def request? @recipient.match(/-request@/) end def automated_message? @recipient.match(/-bounce@/).present? || # Empty Return-Path self.return_path.to_s == '<>' || bounced? end def bounced? @bounced ||= bounce_detected? || (error_status != "unknown") end def error_status @error_status ||= detect_error_code end def keywords return @keywords if @keywords part = first_plaintext_part if part.blank? return [] end @keywords = [] look_for_keywords = true lines = part.decoded.lines.map do |line| # TODO: Find multiline arguments (add-key). Currently add-key has to # read the whole body and hope for the best. if look_for_keywords && (m = line.match(/^x-([^:\s]*)[:\s]*(.*)/i)) command = m[1].strip.downcase arguments = m[2].to_s.strip.downcase.split(/[,; ]{1,}/) @keywords << [command, arguments] nil else if look_for_keywords && line.match(/\S+/i) look_for_keywords = false end line end end # Work around problems with re-encoding the body. If we delete the # content-transfer-encoding prior to re-assigning the body, and let Mail # decide itself how to encode, it works. If we don't, some # character-sequences are not properly re-encoded. part.content_transfer_encoding = nil # Set the right charset on the now parsed body new_body = lines.compact.join part.charset = new_body.encoding.to_s part.body = new_body @keywords end def add_subject_prefix! _add_subject_prefix(nil) end def add_subject_prefix_in! _add_subject_prefix(:in) end def add_subject_prefix_out! _add_subject_prefix(:out) end def add_pseudoheader(string_or_key, value=nil) dynamic_pseudoheaders << make_pseudoheader(string_or_key, value) end def make_pseudoheader(key, value) output = "#{key.to_s.camelize}: #{value.to_s}" # wrap lines after 76 with 2 indents output.gsub(/(.{1,76})( +|$)\n?/, " \\1\n").chomp.lstrip end def dynamic_pseudoheaders @dynamic_pseudoheaders ||= [] end def signature_state # Careful to add information about the incoming signature. GPGME # throws exceptions if it doesn't know the key. if self.signature.present? # Some versions of gpgme return nil if the key is unknown, so we check # for that manually and provide our own fallback. (Calling # `signature.key` results in an EOFError in that case.) if signing_key.present? signature_state = signature.to_s else signature_state = I18n.t("signature_states.unknown", fingerprint: self.signature.fingerprint) end else signature_state = I18n.t("signature_states.unsigned") end signature_state end def encryption_state if was_encrypted? encryption_state = I18n.t("encryption_states.encrypted") else encryption_state = I18n.t("encryption_states.unencrypted") end encryption_state end def standard_pseudoheaders(list) if @standard_pseudoheaders.present? return @standard_pseudoheaders else @standard_pseudoheaders = [] end Array(list.headers_to_meta).each do |field| value = case field.to_s when 'sig' then signature_state when 'enc' then encryption_state else self.header[field.to_s] end @standard_pseudoheaders << make_pseudoheader(field.to_s, value) end @standard_pseudoheaders end def pseudoheaders(list) separator = '------------------------------------------------------------------------------' (standard_pseudoheaders(list) + dynamic_pseudoheaders).flatten.join("\n") + "\n" + separator + "\n" end def add_msgids(list, orig) if list.keep_msgid # Don't use `orig['in-reply-to']` here, because that sometimes fails to # parse the original value and then returns it without the # angle-brackets. self.message_id = clutch_anglebrackets(orig.message_id) self.in_reply_to = clutch_anglebrackets(orig.in_reply_to) self.references = clutch_anglebrackets(orig.references) end end def add_list_headers(list) if list.include_autocrypt_header # Inject whitespaces, to let Mail break the string at these points # leading to correct wrapping. keydata = list.key_minimal_base64_encoded.gsub(/(.{78})/, '\1 ') self['Autocrypt'] = "addr=#{list.email}; prefer-encrypt=mutual; keydata=#{keydata}" end if list.include_list_headers self['List-Id'] = "<#{list.email.gsub('@', '.')}>" self['List-Owner'] = " (Use list's public key)" self['List-Help'] = '' postmsg = if list.receive_admin_only "NO (Admins only)" elsif list.receive_authenticated_only " (Subscribers only)" else "" end self['List-Post'] = postmsg end end def add_openpgp_headers(list) if list.include_openpgp_header if list.openpgp_header_preference == 'none' pref = '' else pref = "preference=#{list.openpgp_header_preference}" # TODO: simplify. pref << ' (' if list.receive_admin_only pref << 'Only encrypted and signed emails by list-admins are accepted' elsif ! list.receive_authenticated_only if list.receive_encrypted_only && list.receive_signed_only pref << 'Only encrypted and signed emails are accepted' elsif list.receive_encrypted_only && ! list.receive_signed_only pref << 'Only encrypted emails are accepted' elsif ! list.receive_encrypted_only && list.receive_signed_only pref << 'Only signed emails are accepted' else pref << 'All kind of emails are accepted' end elsif list.receive_authenticated_only if list.receive_encrypted_only pref << 'Only encrypted and signed emails by subscribers are accepted' else pref << 'Only signed emails by subscribers are accepted' end else pref << 'All kind of emails are accepted' end pref << ')' end fingerprint = list.fingerprint comment = "(Send an email to #{list.sendkey_address} to receive the public-key)" self['OpenPGP'] = "id=0x#{fingerprint} #{comment}; #{pref}" end end def empty? if self.multipart? if self.parts.empty? return true else # Test parts recursively. E.g. Thunderbird with activated # memoryhole-headers send nested parts that might still be empty. return parts.inject(true) { |result, part| result && part.empty? } end else return self.body.empty? end end def first_plaintext_part(part=nil) part ||= self if part.multipart? first_plaintext_part(part.parts.first) elsif part.mime_type == 'text/plain' part else nil end end def attach_list_key!(list) filename = "#{list.email}.asc" self.add_file({ filename: filename, content: list.export_key }) self.attachments[filename].content_type = 'application/pgp-keys' self.attachments[filename].content_description = 'OpenPGP public key' true end private # mail.signed? throws an error if it finds # pgp boundaries, so we must use the Mail::Gpg # methods. def encapsulated_signed?(mail) (mail.verify_result.nil? || mail.verify_result.signatures.empty?) && \ (Mail::Gpg.signed_mime?(mail) || Mail::Gpg.signed_inline?(mail)) end def add_footer!(footer_attribute) if self.list.blank? || self.list.send(footer_attribute).to_s.empty? return end footer_part = Mail::Part.new footer_part.body = self.list.send(footer_attribute).to_s if wrapped_single_text_part? self.parts.first.add_part footer_part else self.add_part footer_part end end def wrapped_single_text_part? parts.size == 1 && parts.first.mime_type == 'multipart/mixed' && parts.first.parts.size == 1 && parts.first.parts.first.mime_type == 'text/plain' end def _add_subject_prefix(suffix) attrib = "subject_prefix" if suffix attrib << "_#{suffix}" end if ! self.list.respond_to?(attrib) return false end string = self.list.send(attrib).to_s.strip if ! string.empty? prefix = "#{string} " # Only insert prefix if it's not present already. if self.subject.nil? self.subject = string elsif ! self.subject.include?(prefix) self.subject = "#{prefix}#{self.subject}" end end end # Looking for signatures in each part. They are not aggregated into the main part. # We only return the signature if all parts are validly signed by the same key. def signature_multipart_inline fingerprints = parts.map do |part| if part.signature_valid? part.signature.fpr else nil end end if fingerprints.uniq.size == 1 parts.first.signature else nil end end def clutch_anglebrackets(input) Array(input).map do |string| if string.first == '<' string else "<#{string}>" end end.join(' ') end def detect_error_code # Detects the error code of an email with different heuristics # from: https://github.com/mailtop/bounce_email # Custom status codes unicode_subject = self.subject.to_s unicode_subject = unicode_subject.encode('utf-8') if unicode_subject.respond_to?(:encode) return '97' if unicode_subject.match(/delayed/i) return '98' if unicode_subject.match(/(unzulässiger|unerlaubter) anhang/i) return '99' if unicode_subject.match(/auto.*reply|férias|ferias|Estarei ausente|estou ausente|vacation|vocation|(out|away).*office|on holiday|abwesenheits|autorespond|Automatische|eingangsbestätigung/i) # Feedback-Type: abuse return '96' if self.to_s.match(/Feedback-Type\: abuse/i) if self.parts[1] match_parts = self.parts[1].body.match(/(Status:.|550 |#)([245]\.[0-9]{1,3}\.[0-9]{1,3})/) code = match_parts[2] if match_parts return code if code end # Now try getting it from correct part of tmail code = detect_bounce_status_code_from_text(self.body) return code if code # OK getting desperate so try getting code from entire email code = detect_bounce_status_code_from_text(self.to_s) code || 'unknown' end def bounce_detected? # Detects bounces from different parts of the email without error status codes # from: https://github.com/mailtop/bounce_email return true if self.subject.to_s.match(/(returned|undelivered) mail|mail delivery( failed)?|(delivery )(status notification|failure)|failure notice|undeliver(able|ed)( mail)?|return(ing message|ed) to sender/i) return true if self.subject.to_s.match(/auto.*reply|vacation|vocation|(out|away).*office|on holiday|abwesenheits|autorespond|Automatische|eingangsbestätigung/i) return true if self['precedence'].to_s.match(/auto.*(reply|responder|antwort)/i) return true if self.from.to_s.match(/^(MAILER-DAEMON|POSTMASTER)\@/i) false end def detect_bounce_status_code_from_text(text) # Parses a text and uses pattern matching to determines its error status (RFC 3463) # from: https://github.com/mailtop/bounce_email return "5.0.0" if text.match(/Status: 5\.0\.0/i) return "5.1.1" if text.match(/no such (address|user)|Recipient address rejected|User unknown|does not like recipient|The recipient was unavailable to take delivery of the message|Sorry, no mailbox here by that name|invalid address|unknown user|unknown local part|user not found|invalid recipient|failed after I sent the message|did not reach the following recipient|nicht zugestellt werden|o pode ser entregue para um ou mais/i) return "5.1.2" if text.match(/unrouteable mail domain|Esta casilla ha expirado por falta de uso|I couldn't find any host named/i) if text.match(/mailbox is full|Mailbox quota (usage|disk) exceeded|quota exceeded|Over quota|User mailbox exceeds allowed size|Message rejected\. Not enough storage space|user has exhausted allowed storage space|too many messages on the server|mailbox is over quota|mailbox exceeds allowed size|excedeu a quota/i) return "5.2.2" if text.match(/This is a permanent error||(Status: |)5\.2\.2/i) return "4.2.2" end return "5.1.0" if text.match(/Address rejected/) return "4.1.2" if text.match(/I couldn't find any host by that name/) return "4.2.0" if text.match(/not yet been delivered/i) return "5.1.1" if text.match(/mailbox unavailable|No such mailbox|RecipientNotFound|not found by SMTP address lookup|Status: 5\.1\.1/i) return "5.2.3" if text.match(/Status: 5\.2\.3/i) # Too messages in folder return "5.4.0" if text.match(/Status: 5\.4\.0/i) # too many hops return "5.4.4" if text.match(/Unrouteable address/i) return "4.4.7" if text.match(/retry timeout exceeded/i) return "5.2.0" if text.match(/The account or domain may not exist, they may be blacklisted, or missing the proper dns entries./i) return "5.5.4" if text.match(/554 TRANSACTION FAILED/i) return "4.4.1" if text.match(/Status: 4.4.1|delivery temporarily suspended|wasn't able to establish an SMTP connection/i) return "5.5.0" if text.match(/550 OU\-002|Mail rejected by Windows Live Hotmail for policy reasons/i) return "5.1.2" if text.match(/PERM_FAILURE: DNS Error: Domain name not found/i) return "4.2.0" if text.match(/Delivery attempts will continue to be made for/i) return "5.5.4" if text.match(/554 delivery error:/i) return "5.1.1" if text.match(/550-5.1.1|This Gmail user does not exist/i) return "5.7.1" if text.match(/5.7.1 Your message.*?was blocked by ROTA DNSBL/i) # AA added return "5.7.2" if text.match(/not have permission to post messages to the group/i) return "5.3.2" if text.match(/Technical details of permanent failure|Too many bad recipients/i) && (text.match(/The recipient server did not accept our requests to connect/i) || text.match(/Connection was dropped by remote host/i) || text.match(/Could not initiate SMTP conversation/i)) # AA added return "4.3.2" if text.match(/Technical details of temporary failure/i) && (text.match(/The recipient server did not accept our requests to connect/i) || text.match(/Connection was dropped by remote host/i) || text.match(/Could not initiate SMTP conversation/i)) # AA added return "5.0.0" if text.match(/Delivery to the following recipient failed permanently/i) # AA added return '5.2.3' if text.match(/account closed|account has been disabled or discontinued|mailbox not found|prohibited by administrator|access denied|account does not exist/i) end end end schleuder-3.6.0/lib/schleuder/mail/parts_list.rb000066400000000000000000000004211401002544500216450ustar00rootroot00000000000000module Mail class PartsList # Disable sorting of mime-parts completely. # Can't be done during runtime on the body-instance (`body#set_sort_order`) # because MailGpg exchanges the body-instances when encrypting/signing. def sort!(*args) end end end schleuder-3.6.0/lib/schleuder/plugin_runners/000077500000000000000000000000001401002544500212675ustar00rootroot00000000000000schleuder-3.6.0/lib/schleuder/plugin_runners/base.rb000066400000000000000000000051031401002544500225250ustar00rootroot00000000000000module Schleuder module PluginRunners module Base def run(list, mail) list.logger.debug "Starting #{self}" @list = list @mail = mail setup output = mail.keywords.map do |keyword, arguments| run_plugin(keyword, arguments) end output.flatten.compact end private def run_plugin(keyword, arguments) @list.logger.debug "Running keyword '#{keyword}'" error = check_admin_only(keyword) return error if error command = keyword.gsub('-', '_') if ['list_name', 'listname'].include? (command) return nil elsif ! @plugin_module.respond_to?(command) return I18n.t('plugins.unknown_keyword', keyword: keyword) else response = run_command(command, arguments) if @list.keywords_admin_notify.include?(keyword) notify_admins(keyword, arguments, response) end return response end rescue => exc # Log to system, this information is probably more useful for # system-admins than for list-admins. Schleuder.logger.error(exc.message_with_backtrace) I18n.t("plugins.plugin_failed", keyword: keyword) end def run_command(command, arguments) out = @plugin_module.send(command, arguments, @list, @mail) Array(out).flatten end def check_admin_only(keyword) if @list.admin_only?(keyword) && ! @list.from_admin?(@mail) @list.logger.debug "Error: Keyword is admin-only, sent by non-admin" Schleuder::Errors::KeywordAdminOnly.new(keyword).to_s else false end end def setup check_listname_keyword load_plugin_files @plugin_module = self.name.demodulize.gsub("Runner", "").constantize end def check_listname_keyword return nil if @mail.keywords.blank? listname_kw = @mail.keywords.assoc('list-name') || @mail.keywords.assoc('listname') if listname_kw.blank? @mail.reply_to_signer I18n.t(:missing_listname_keyword_error) exit else listname_args = listname_kw.last if ! [@list.email, @list.request_address].include?(listname_args.first) @mail.reply_to_signer I18n.t(:wrong_listname_keyword_error) exit end end end def load_plugin_files @list.logger.debug "Loading plugins" Dir["#{Schleuder::Conf.plugins_dir}/*.rb"].each do |file| require file end end end end end schleuder-3.6.0/lib/schleuder/plugin_runners/list_plugins_runner.rb000066400000000000000000000013611401002544500257220ustar00rootroot00000000000000module Schleuder module PluginRunners module ListPluginsRunner extend Base def self.notify_admins(keyword, arguments, response) if arguments.blank? msg = I18n.t('plugins.keyword_admin_notify_lists_without_arguments', signer: @mail.signer, keyword: keyword ) else msg = I18n.t('plugins.keyword_admin_notify_lists', signer: @mail.signer, keyword: keyword, arguments: arguments.join(' ') ) end @list.logger.notify_admin(msg, nil, 'Notice') end end end end schleuder-3.6.0/lib/schleuder/plugin_runners/request_plugins_runner.rb000066400000000000000000000015401401002544500264360ustar00rootroot00000000000000module Schleuder module PluginRunners module RequestPluginsRunner extend Base def self.notify_admins(keyword, arguments, response) if arguments.blank? explanation = I18n.t('plugins.keyword_admin_notify_request_without_arguments', signer: @mail.signer, keyword: keyword ) else explanation = I18n.t('plugins.keyword_admin_notify_request', signer: @mail.signer, keyword: keyword, arguments: arguments.join(' ') ) end response = response.join("\n\n") msg = "#{explanation}\n\n#{response}" @list.logger.notify_admin(msg, nil, 'Notice') end end end end schleuder-3.6.0/lib/schleuder/plugins/000077500000000000000000000000001401002544500176765ustar00rootroot00000000000000schleuder-3.6.0/lib/schleuder/plugins/attach_listkey.rb000066400000000000000000000006571401002544500232430ustar00rootroot00000000000000module Schleuder module ListPlugins def self.attach_listkey(arguments, list, mail) new_part = Mail::Part.new new_part.body = list.export_key new_part.content_type = 'application/pgp-keys' new_part.content_description = "OpenPGP public key of #{list.email}" new_part.content_disposition = "attachment; filename=#{list.fingerprint}.pgpkey" mail.add_part new_part nil end end end schleuder-3.6.0/lib/schleuder/plugins/get_version.rb000066400000000000000000000002041401002544500225430ustar00rootroot00000000000000module Schleuder module RequestPlugins def self.get_version(arguments, list, mail) Schleuder::VERSION end end end schleuder-3.6.0/lib/schleuder/plugins/key_management.rb000066400000000000000000000066121401002544500232140ustar00rootroot00000000000000module Schleuder module RequestPlugins def self.add_key(arguments, list, mail) if mail.has_attachments? results = self.import_keys_from_attachments(list, mail) else results = [self.import_key_from_body(list, mail)] end import_stati = results.compact.collect(&:imports).flatten if import_stati.blank? return I18n.t('plugins.key_management.no_imports') end out = [] import_stati.each do |import_status| if import_status.action == 'error' out << I18n.t("plugins.key_management.key_import_status.error", fingerprint: import_status.fingerprint) else key = list.gpg.find_distinct_key(import_status.fingerprint) if key out << I18n.t("plugins.key_management.key_import_status.#{import_status.action}", key_oneline: key.oneline) end end end out.join("\n\n") end def self.delete_key(arguments, list, mail) if arguments.blank? return I18n.t( "plugins.key_management.delete_key_requires_arguments" ) end arguments.map do |argument| keys = list.keys(argument) case keys.size when 0 I18n.t("errors.no_match_for", input: argument) when 1 begin keys.first.delete! I18n.t('plugins.key_management.deleted', key_string: keys.first.oneline) rescue GPGME::Error::Conflict I18n.t('plugins.key_management.not_deletable', key_string: keys.first.oneline) end else I18n.t('errors.too_many_matching_keys', { input: argument, key_strings: keys.map(&:to_s).join("\n") }) end end.join("\n\n") end def self.list_keys(arguments, list, mail) args = Array(arguments.presence || '') args.map do |argument| # In this case it shall be allowed to match keys by arbitrary # sub-strings, therefore we use `list.gpg` directly to not have the # input filtered. list.gpg.keys(argument).map do |key| key.to_s end end.join("\n\n") end def self.get_key(arguments, list, mail) arguments.map do |argument| keys = list.keys(argument) if keys.blank? I18n.t("errors.no_match_for", input: argument) else result = [I18n.t('plugins.key_management.matching_keys_intro', input: argument)] keys.each do |key| atchm = Mail::Part.new atchm.body = key.armored atchm.content_type = 'application/pgp-keys' atchm.content_disposition = "attachment; filename=#{key.fingerprint}.asc" result << atchm end result.flatten end end end def self.fetch_key(arguments, list, mail) if arguments.blank? return I18n.t( "plugins.key_management.fetch_key_requires_arguments" ) end arguments.map do |argument| list.fetch_keys(argument) end end # helper methods private def self.import_keys_from_attachments(list, mail) mail.attachments.map do |attachment| material = attachment.body.to_s list.import_key(material) end end def self.import_key_from_body(list, mail) key_material = mail.first_plaintext_part.body.to_s list.import_key(key_material) end end end schleuder-3.6.0/lib/schleuder/plugins/list_management.rb000066400000000000000000000010121401002544500233640ustar00rootroot00000000000000module Schleuder module RequestPlugins def self.get_logfile(arguments, list, mail) if File.readable?(list.logfile) attachment = Mail::Part.new attachment.body = File.read(list.logfile) attachment.content_disposition = "inline; filename=#{list.email}.log" intro = I18n.t("plugins.list_management.logfile_attached", listname: list.email) [intro, attachment] else I18n.t("plugins.list_management.no_logfile", listname: list.email) end end end end schleuder-3.6.0/lib/schleuder/plugins/resend.rb000066400000000000000000000136251401002544500215120ustar00rootroot00000000000000module Schleuder module ListPlugins def self.resend(arguments, list, mail) resend_it(arguments, mail, false) end def self.resend_enc(arguments, list, mail) resend_encrypted_only(arguments, list, mail) end def self.resend_encrypted_only(arguments, list, mail) resend_it(arguments, mail, true) end def self.resend_cc(arguments, list, mail) resend_it_cc(arguments, mail, false) end def self.resend_cc_enc(arguments, list, mail) resend_cc_encrypted_only(arguments, list, mail) end def self.resend_cc_encrypted_only(arguments, list, mail) resend_it_cc(arguments, mail, true) end def self.resend_unencrypted(arguments, list, mail) do_resend_unencrypted(arguments, list, mail, :to) end def self.resend_cc_unencrypted(arguments, list, mail) do_resend_unencrypted(arguments, list, mail, :cc) end # helper methods private def self.do_resend_unencrypted(arguments, list, mail, target) if ! resend_recipients_valid?(mail, arguments) return false end recip_map = Hash[Array(arguments).map{|email| [email,''] }] if do_resend(mail, recip_map, target, false) mail.add_subject_prefix_out! end end def self.resend_it_cc(arguments, mail, encrypted_only) if ! resend_recipients_valid?(mail, arguments) return false end recip_map = map_with_keys(mail, arguments, encrypted_only) # Only continue if all recipients are still here. if recip_map.size < arguments.size recip_map.keys.each do |aborted_sender| mail.add_pseudoheader(:error, I18n.t("plugins.resend.aborted", email: aborted_sender)) end return end if do_resend(mail, recip_map, :cc, encrypted_only) mail.add_subject_prefix_out! end end def self.resend_it(arguments, mail, encrypted_only) if ! resend_recipients_valid?(mail, arguments) return false end recip_map = map_with_keys(mail, arguments, encrypted_only) resent_stati = recip_map.map do |email, key| do_resend(mail, {email => key}, :to, encrypted_only) end if resent_stati.include?(true) # At least one message has been resent mail.add_subject_prefix_out! end end def self.do_resend(mail, recipients_map, to_or_cc, encrypted_only) if recipients_map.empty? return end gpg_opts = make_gpg_opts(mail, recipients_map, encrypted_only) if gpg_opts == false return false end # Compose and send email new = mail.clean_copy new[to_or_cc] = recipients_map.keys new.add_public_footer! new.sender = mail.list.bounce_address # `dup` gpg_opts because `deliver` changes their value and we need them # below to determine encryption! new.gpg gpg_opts.dup if new.deliver add_resent_headers(mail, recipients_map, to_or_cc, gpg_opts[:encrypt]) return true else add_error_header(mail, recipients_map) return false end rescue Net::SMTPFatalError => exc add_error_header(mail, recipients_map) logger.error "Error while sending: #{exc}" return false end def self.map_with_keys(mail, recipients, encrypted_only) Array(recipients).inject({}) do |hash, email| keys = mail.list.keys(email) # Exclude unusable keys. usable_keys = keys.select { |key| key.usable_for?(:encrypt) } case usable_keys.size when 1 hash[email] = usable_keys.first when 0 if encrypted_only # Don't add the email to the result to exclude it from the # recipients. add_resend_msg(mail, email, :error, 'not_resent_no_keys', usable_keys.size, keys.size) else hash[email] = '' end else # Always report this situation, regardless of sending or not. It's # bad and should be fixed. add_resend_msg(mail, email, :notice, 'not_resent_encrypted_no_keys', usable_keys.size, keys.size) if ! encrypted_only hash[email] = '' end end hash end end def self.make_gpg_opts(mail, recipients_map, encrypted_only) gpg_opts = mail.list.gpg_sign_options # Do all recipients have a key? if recipients_map.values.map(&:class).uniq == [GPGME::Key] gpg_opts.merge!(encrypt: true) elsif encrypted_only false end gpg_opts end def self.add_resend_msg(mail, email, severity, msg, usable_keys_size, all_keys_size) mail.add_pseudoheader(severity, I18n.t("plugins.resend.#{msg}", email: email, usable_keys: usable_keys_size, all_keys: all_keys_size)) end def self.add_error_header(mail, recipients_map) mail.add_pseudoheader(:error, "Resending to #{recipients_map.keys.join(', ')} failed, please check the logs!") end def self.add_resent_headers(mail, recipients_map, to_or_cc, sent_encrypted) if sent_encrypted prefix = I18n.t('plugins.resend.encrypted_to') str = "\n" + recipients_map.map do |email, key| "#{email} (#{key.fingerprint})" end.join(",\n") else prefix = I18n.t('plugins.resend.unencrypted_to') str = ' ' + recipients_map.keys.join(", ") end headername = resent_header_name(to_or_cc) mail.add_pseudoheader(headername, "#{prefix}#{str}") end def self.resent_header_name(to_or_cc) if to_or_cc.to_s == 'to' 'resent' else 'resent_cc' end end def self.resend_recipients_valid?(mail, recipients) all_valid = true Array(recipients).each do |address| if ! address.match(Conf::EMAIL_REGEXP) mail.add_pseudoheader(:error, I18n.t("plugins.resend.invalid_recipient", address: address)) all_valid = false end end all_valid end end end schleuder-3.6.0/lib/schleuder/plugins/sign_this.rb000066400000000000000000000026171401002544500222200ustar00rootroot00000000000000module Schleuder module RequestPlugins def self.sign_this(arguments, list, mail) if mail.has_attachments? list.logger.debug "Signing each attachment's body" intro = I18n.t('plugins.signatures_attached') parts = mail.attachments.map do |attachment| make_signature_part(attachment, list) end [intro, parts].flatten else list.logger.debug "Clear-signing first available text/plain part" clearsign(mail.first_plaintext_part) end end # helper methods private def self.make_signature_part(attachment, list) material = attachment.body.to_s return nil if material.strip.blank? file_basename = attachment.filename.presence || Digest::SHA256.hexdigest(material) list.logger.debug "Signing #{file_basename}" filename = "#{file_basename}.sig" part = Mail::Part.new part.body = detachsign(material) part.content_type = 'application/pgp-signature' part.content_disposition = "attachment; filename=#{filename}" part.content_description = "OpenPGP signature for '#{file_basename}'" part end def self.detachsign(thing) crypto.sign(thing, mode: GPGME::SIG_MODE_DETACH).to_s end def self.clearsign(mail) crypto.clearsign(mail.body.to_s).to_s end def self.crypto @crypto ||= GPGME::Crypto.new(armor: true) end end end schleuder-3.6.0/lib/schleuder/plugins/subscription_management.rb000066400000000000000000000134411401002544500251460ustar00rootroot00000000000000module Schleuder module RequestPlugins def self.subscribe(arguments, list, mail) if arguments.blank? return I18n.t( "plugins.subscription_management.subscribe_requires_arguments" ) end email = arguments.shift if arguments.present? # Collect all arguments that look like fingerprint-material fingerprint = '' while arguments.first.present? && arguments.first.match(/^(0x)?[a-f0-9]+$/i) fingerprint << arguments.shift end # Use possibly remaining args as flags. adminflag = arguments.shift deliveryflag = arguments.shift end sub, _ = list.subscribe(email, fingerprint, adminflag, deliveryflag) if sub.persisted? I18n.t( "plugins.subscription_management.subscribed", email: sub.email, fingerprint: sub.fingerprint, admin: sub.admin, delivery_enabled: sub.delivery_enabled ) else I18n.t( "plugins.subscription_management.subscribing_failed", email: sub.email, errors: sub.errors.full_messages.join(".\n") ) end end def self.unsubscribe(arguments, list, mail) # If no address was given we unsubscribe the sender. email = arguments.first.presence || mail.signer.email # Refuse to unsubscribe the last admin. if list.admins.size == 1 && list.admins.first.email == email return I18n.t( "plugins.subscription_management.cannot_unsubscribe_last_admin", email: email ) end # TODO: May signers have multiple UIDs? We don't match those currently. if ! list.from_admin?(mail) && email != mail.signer.email # Only admins may unsubscribe others. return I18n.t( "plugins.subscription_management.forbidden", email: email ) end sub = list.subscriptions.where(email: email).first if sub.blank? return I18n.t( "plugins.subscription_management.is_not_subscribed", email: email ) end if res = sub.delete I18n.t( "plugins.subscription_management.unsubscribed", email: email ) else I18n.t( "plugins.subscription_management.unsubscribing_failed", email: email, error: res.errors.to_a ) end end def self.list_subscriptions(arguments, list, mail) subs = if arguments.blank? list.subscriptions.all.to_a else arguments.map do |argument| list.subscriptions.where("email like ?", "%#{argument}%").to_a end.flatten end if subs.blank? return nil end out = [ I18n.t("plugins.subscription_management.list_of_subscriptions") ] out << subs.map do |subscription| # Fingerprints are at most 40 characters long, and lines shouldn't # exceed 80 characters if possible. s = subscription.email if subscription.fingerprint.present? s << "\t0x#{subscription.fingerprint}" end if ! subscription.delivery_enabled? s << "\tDelivery disabled!" end s end out.join("\n") end def self.set_fingerprint(arguments, list, mail) if arguments.blank? return I18n.t( "plugins.subscription_management.set_fingerprint_requires_arguments" ) end if arguments.first.match(/@/) if arguments.first == mail.signer.email || list.from_admin?(mail) email = arguments.shift else return I18n.t( "plugins.subscription_management.set_fingerprint_only_self" ) end else email = mail.signer.email end sub = list.subscriptions.where(email: email).first if sub.blank? return I18n.t( "plugins.subscription_management.is_not_subscribed", email: email ) end fingerprint = arguments.join unless GPGME::Key.valid_fingerprint?(fingerprint) return I18n.t( "plugins.subscription_management.set_fingerprint_requires_valid_fingerprint", fingerprint: fingerprint ) end sub.fingerprint = fingerprint if sub.save I18n.t( "plugins.subscription_management.fingerprint_set", email: email, fingerprint: sub.fingerprint ) else I18n.t( "plugins.subscription_management.setting_fingerprint_failed", email: email, fingerprint: sub.fingerprint, errors: sub.errors.to_a.join("\n") ) end end def self.unset_fingerprint(arguments, list, mail) if arguments.blank? return I18n.t( "plugins.subscription_management.unset_fingerprint_requires_arguments" ) end email = arguments.first unless email == mail.signer.email || list.from_admin?(mail) return I18n.t( "plugins.subscription_management.unset_fingerprint_only_self" ) end if email == mail.signer.email && list.from_admin?(mail) && arguments.last != 'force' return I18n.t( "plugins.subscription_management.unset_fingerprint_requires_arguments" ) end sub = list.subscriptions.where(email: email).first if sub.blank? return I18n.t( "plugins.subscription_management.is_not_subscribed", email: email ) end sub.fingerprint = '' if sub.save I18n.t( "plugins.subscription_management.fingerprint_unset", email: email ) else I18n.t( "plugins.subscription_management.unsetting_fingerprint_failed", email: email, errors: sub.errors.to_a.join("\n") ) end end end end schleuder-3.6.0/lib/schleuder/runner.rb000066400000000000000000000122361401002544500200570ustar00rootroot00000000000000module Schleuder class Runner def run(msg, recipient) error = setup_list(recipient) return error if error logger.info "Parsing incoming email." # is it valid utf-8? msg_scrubbed = false unless msg.valid_encoding? logger.warn "Converting message due to invalid characters" detection = CharlockHolmes::EncodingDetector.detect(msg) begin msg = CharlockHolmes::Converter.convert(msg, detection[:encoding], 'UTF-8') rescue ArgumentError # it looks like even icu wasn't able to convert # so we scrub the invalid characters to be able to # at least parse the message somehow. Though this might # result in data loss. logger.warn "Scrubbing message due to invalid characters" msg = msg.scrub msg_scrubbed = true end end @mail = Mail.create_message_to_list(msg, recipient, list) if msg_scrubbed @mail.add_pseudoheader(:note, I18n.t("pseudoheaders.scrubbed_message")) end error = run_filters('pre') return error if error begin # This decrypts, verifies, etc. @mail = @mail.setup rescue GPGME::Error::BadPassphrase, GPGME::Error::DecryptFailed, GPGME::Error::NoData, GPGME::Error::NoSecretKey logger.warn "Decryption of incoming message failed." return Errors::DecryptionFailed.new(list) end error = run_filters('post') return error if error if ! @mail.was_validly_signed? logger.debug "Message was not validly signed, adding subject_prefix_in" @mail.add_subject_prefix_in! end if ! @mail.was_encrypted? logger.debug "Message was not encrypted, skipping plugins" elsif @mail.was_validly_signed? # Plugins logger.debug "Message was encrypted and validly signed" PluginRunners::ListPluginsRunner.run(list, @mail).compact end # Don't send empty messages over the list. if @mail.empty? logger.info "Message found empty, not sending it to list." return Errors::MessageEmpty.new(@list) end logger.debug "Adding subject_prefix" @mail.add_subject_prefix! # Subscriptions logger.debug "Creating clean copy of message" copy = @mail.clean_copy(list.headers_to_meta.any?) list.send_to_subscriptions(copy, @mail) nil end private def list @list end def run_filters(filter_type) error = filters_runner(filter_type).run(@mail) if error if list.bounces_notify_admins? text = "#{I18n.t('.bounces_notify_admins')}\n\n#{error}" # TODO: raw_source is mostly blank? logger.notify_admin text, @mail.original_message, I18n.t('notice') end return error end end def filters_runner(filter_type) if filter_type == 'pre' filters_runner_pre_decryption else filters_runner_post_decryption end end def filters_runner_pre_decryption @filters_runner_pre_decryption ||= Filters::Runner.new(list,'pre') end def filters_runner_post_decryption @filters_runner_post_decryption ||= Filters::Runner.new(list,'post') end def logger list.present? && list.logger || Schleuder.logger end def log_and_return(error, reveal_error=false) Schleuder.logger.error(error) if reveal_error error else # Return an unrevealing error, the sender and all bystanders don't need to know these details. Errors::FatalError.new end end def setup_list(recipient) return @list if @list logger.info "Loading list '#{recipient}'" if ! @list = List.by_recipient(recipient) return log_and_return(Errors::ListNotFound.new(recipient), true) end # Check necessary permissions of crucial files. if ! File.exist?(@list.listdir) return log_and_return(Errors::ListdirProblem.new(@list.listdir, :not_existing)) elsif ! File.directory?(@list.listdir) return log_and_return(Errors::ListdirProblem.new(@list.listdir, :not_a_directory)) elsif ! File.readable?(@list.listdir) return log_and_return(Errors::ListdirProblem.new(@list.listdir, :not_readable)) elsif ! File.writable?(@list.listdir) return log_and_return(Errors::ListdirProblem.new(@list.listdir, :not_writable)) else if File.exist?(@list.logfile) && ! File.writable?(@list.logfile) return log_and_return(Errors::ListdirProblem.new(@list.logfile, :not_writable)) end end # Check basic sanity of list. %w[fingerprint key secret_key admins].each do |attrib| if @list.send(attrib).blank? return log_and_return(Errors::ListPropertyMissing.new(@list.listdir, attrib)) end end # Set locale if I18n.available_locales.include?(@list.language.to_sym) I18n.locale = @list.language.to_sym end # This cannot be put in List, as Mail wouldn't know it then. logger.debug "Setting GNUPGHOME to #{@list.listdir}" ENV['GNUPGHOME'] = @list.listdir nil end end end schleuder-3.6.0/lib/schleuder/subscription.rb000066400000000000000000000077051401002544500212770ustar00rootroot00000000000000module Schleuder class Subscription < ActiveRecord::Base belongs_to :list validates :list_id, inclusion: { in: -> (id) { List.pluck(:id) }, message: "must refer to an existing list" } validates :email, presence: true, email: true, uniqueness: {scope: :list_id} validates :fingerprint, allow_blank: true, fingerprint: true validates :delivery_enabled, :admin, boolean: true before_validation { self.email = Mail::Address.new(self.email).address } default_scope { order(:email) } scope :without_fingerprint, -> { where(fingerprint: [nil,'']) } def to_s email end def self.configurable_attributes [:fingerprint, :admin, :delivery_enabled] end def fingerprint=(arg) # Always assign the given value, because it must be possible to overwrite # the previous fingerprint with an empty value. That value should better # be nil instead of a blank string, but currently schleuder-cli (v0.1.0) expects # only strings. write_attribute(:fingerprint, arg.to_s.gsub(/\s*/, '').gsub(/^0x/, '').chomp.upcase) end def key # TODO: make key-related methods a concern, so we don't have to go # through the list and neither re-implement the methods here. # Prefix '0x' to force GnuPG to match only hex-values, not UIDs. list.keys("0x#{self.fingerprint}").first end def send_mail(mail, incoming_mail=nil) list.logger.debug "Preparing sending to #{self.inspect}" mail = ensure_headers(mail, incoming_mail) gpg_opts = self.list.gpg_sign_options if self.key.blank? if self.list.send_encrypted_only? notify_of_missed_message(:absent) return false else list.logger.warn "Sending plaintext because no key is present!" end elsif ! self.key.usable? if self.list.send_encrypted_only? notify_of_missed_message(key.usability_issue) return false else list.logger.warn "Sending plaintext because assigned key is #{key.usability_issue}!" end else gpg_opts.merge!(encrypt: true, keys: {self.email => "0x#{self.fingerprint}"}) end list.logger.info "Sending message to #{self.email}" mail.gpg gpg_opts mail.deliver end def ensure_headers(mail, incoming_mail=nil) mail.to = self.email if self.list.set_reply_to_to_sender? && ! incoming_mail.nil? # If the option "set_reply_to_to_sender" is set to true, we will set the reply-to header # to the reply-to header given by the original email. If no reply-to header exists in the original email, # the original senders email will be used as reply-to. if ! incoming_mail.reply_to.nil? mail.reply_to = incoming_mail.reply_to else mail.reply_to = incoming_mail.from end end if self.list.munge_from? && ! incoming_mail.nil? # If the option "munge_from" is set to true, we will add the original senders' from-header to ours. # We munge the from-header to avoid issues with DMARC. mail.from = I18n.t("header_munging", from: incoming_mail.from.first, list: self.list.email, list_address: self.list.email) else mail.from = self.list.email end mail.sender = self.list.bounce_address mail end def notify_of_missed_message(reason) self.list.logger.warn "Not sending to #{self.email}: key is unusable because it is #{reason} and sending plain text not allowed" mail = ensure_headers(Mail.new) mail.subject = I18n.t('notice') mail.body = I18n.t("missed_message_due_to_unusable_key", list_email: self.list.email) + I18n.t('errors.signoff') mail.gpg self.list.gpg_sign_options mail.deliver end def admin? self.admin == true end def delete_key list.delete_key(self.fingerprint) end end end schleuder-3.6.0/lib/schleuder/validators/000077500000000000000000000000001401002544500203655ustar00rootroot00000000000000schleuder-3.6.0/lib/schleuder/validators/boolean_validator.rb000066400000000000000000000003401401002544500243730ustar00rootroot00000000000000class BooleanValidator < ActiveModel::EachValidator def validate_each(record, attribute, value) if ! [true, false].include?(value) record.errors.add(attribute, I18n.t("errors.must_be_boolean")) end end end schleuder-3.6.0/lib/schleuder/validators/email_validator.rb000066400000000000000000000003621401002544500240470ustar00rootroot00000000000000class EmailValidator < ActiveModel::EachValidator def validate_each(record, attribute, value) unless value =~ Conf::EMAIL_REGEXP record.errors[attribute] << (options[:message] || I18n.t("errors.invalid_email")) end end end schleuder-3.6.0/lib/schleuder/validators/fingerprint_validator.rb000066400000000000000000000004071401002544500253070ustar00rootroot00000000000000class FingerprintValidator < ActiveModel::EachValidator def validate_each(record, attribute, value) unless GPGME::Key.valid_fingerprint?(value) record.errors[attribute] << (options[:message] || I18n.t("errors.invalid_fingerprint")) end end end schleuder-3.6.0/lib/schleuder/validators/greater_than_zero_validator.rb000066400000000000000000000003431401002544500264610ustar00rootroot00000000000000class GreaterThanZeroValidator < ActiveModel::EachValidator def validate_each(record, attribute, value) if value.to_i == 0 record.errors.add(attribute, I18n.t("errors.must_be_greater_than_zero")) end end end schleuder-3.6.0/lib/schleuder/validators/no_line_breaks_validator.rb000066400000000000000000000003361401002544500257330ustar00rootroot00000000000000class NoLineBreaksValidator < ActiveModel::EachValidator def validate_each(record, attribute, value) if value.to_s.include?("\n") record.errors.add(attribute, I18n.t("errors.no_linebreaks") ) end end end schleuder-3.6.0/lib/schleuder/version.rb000066400000000000000000000000511401002544500202230ustar00rootroot00000000000000module Schleuder VERSION = '3.6.0' end schleuder-3.6.0/locales/000077500000000000000000000000001401002544500151135ustar00rootroot00000000000000schleuder-3.6.0/locales/de.yml000066400000000000000000000372421401002544500162360ustar00rootroot00000000000000de: errors: attributes: language: inclusion: "muss einem der folgenden Werte entsprechen: en, de" log_level: inclusion: "muss einem der folgenden Werte entsprechen: debug, info, warn, error" openpgp_header_preference: inclusion: "muss einem der folgenden Werte entsprechen: sign, encrypt, signencrypt, unprotected, none" internal_footer: invalid: "enthält nicht druckbare Zeichen" public_footer: invalid: "enthält nicht druckbare Zeichen" invalid_email: "ist keine valide E-Mail-Adresse" invalid_fingerprint: "ist kein valider OpenPGP-Fingerabdruck" list_fingerprint_missing: "Fingerabdruck der Liste ist nicht gesetzt, kann nicht arbeiten! (In `%{listdir}`.)" list_key_missing: "Schlüssel der Liste nicht im Schlüsselring gefunden, kann nicht arbeiten! (In `%{listdir}`.)" list_secret_key_missing: "Geheimer Schlüssel der Liste nicht im Schlüsselring gefunden, kann nicht arbeiten! (In `%{listdir}`.)" list_admins_missing: "List hat keine Admins konfiguriert, kann nicht arbeiten! (In `%{listdir}`.)" fatalerror: | Es ist ein schwerwiegender Fehler aufgetreten. Administratoren wurden benachrichtigt. Bitte versuche es später noch ein Mal. signoff: | Freundliche Grüße, Dein Schleuder-System. decryption_failed: | Deine Email konnnte nicht entschlüsselt werden. Emails an diese Adresse müssen mit diesem Schlüssel verschlüsselt werden: %{key} Um den Schlüssel zugesandt zu bekommen sende eine Email an <%{sendkey_email}>. message_unsigned: Emails an diese Adresse müssen mit einem OpenPGP-Schlüssel signiert sein. message_signature_unknown: | Emails an diese Adresse müssen mit dem OpenPGP-Schlüssel signiert sein, der für dein Abo eingetragen ist. Wenn du nicht weisst, welcher Schlüssel das ist, frage die Administrator/innen. Die erreichst du per Email an <%{owner_email}>. (Vorzugsweise verschlüssele die Email mit dem Schlüssel dieser Adresse: %{list_fingerprint}). message_unencrypted: Emails an diese Adresse müssen OpenPGP-konform verschlüsselt sein. message_unauthenticated: Emails an diese Adresse müssen verschlüsselt und mit einem OpenPGP-Schlüssel signiert sein, der für ein Abo eingetragen ist. message_sender_not_subscribed: Nur Absender mit Abo dürfen Emails an diese Adresse schicken. message_not_from_admin: Nur Admins dürfen Emails an diese Adresse schicken. message_empty: | Deine Email enthielt keinen Text, daher wurde sie nicht über die Liste verteilt. Falls du ausschließlich Schlüsselwörter gesendet hast beachte, dass administrative Schlüsselwörter an die "request"-Adresse (<%{request_address}>) geschickt werden müssen um berücksichtigt zu werden. list_not_found: "Fehler: Keine Liste zu dieser Adresse gefunden: '%{email}'." no_linebreaks: "Darf keine Zeilenumbrüche enthalten" invalid_characters: "enthält ungültige Zeichen" listdir_problem: message: "Problem mit dem Listen-Verzeichnis: '%{dir}' %{problem}." not_existing: existiert nicht not_a_directory: ist kein Verzeichnis not_empty: ist nicht leer not_writable: ist nicht beschreibbar not_readable: ist nicht lesbar keyword_admin_only: Das Schlüsselwort '%{keyword}' darf nur von Listen-Admins verwendet werden. key_generation_failed: Das Erzeugen des OpenPGP-Schlüsselpaares für %{listname} ist aus unbekannten Gründen fehlgeschlagen. Bitte prüfe das Listen-Verzeichnis ('%{listdir}') und die Log-Dateien. key_adduid_failed: "Das Hinzufügen einer User-ID zum OpenPGP-Schlüssel ist mit folgender Meldung fehlgeschlagen:\n%{errmsg}" too_many_keys: "Fehler: In %{listdir} existieren mehrere OpenPGP-Schlüssel für %{listname}. Bitte lösche alle bis auf einen." loading_list_settings_failed: "%{config_file} konnte nicht eingelesen werden, bitte Formatierung auf gültiges YAML prüfen." message_too_big: "Deine Email war zu groß. Erlaubt sind für diese Liste %{allowed_size}KB." must_be_boolean: "muss true oder false sein" must_be_greater_than_zero: "muss größer als null sein" not_pgp_mime: "Deine Email war nicht im pgp/mime-Format verschlüsselt." delivery_error: "Beim Versenden einer Email an %{email} ist der folgende Fehler aufgetreten: %{error}" no_match_for: "Keine Treffer für %{input}" too_many_matching_keys: | Zu viele Schlüssel gefunden für '%{input}': %{key_strings} plugins: unknown_keyword: Unbekanntes Schlüsselwort '%{keyword}'. plugin_failed: Das Schlüsselwort '%{keyword}' verursachte einen unbekannten Fehler. Die System-Administratoren wurden benachrichtigt. keyword_admin_notify_request: "%{signer} schickte das Schlüsselwort '%{keyword}' mit den Werten '%{arguments}' und erhielt dies als Antwort:" keyword_admin_notify_request_without_arguments: "%{signer} schickte das Schlüsselwort '%{keyword}' und erhielt dies als Antwort:" keyword_admin_notify_lists: "%{signer} benutzte das Schlüsselwort '%{keyword}' mit den Werten '%{arguments}' in einer Email an die Liste." keyword_admin_notify_lists_without_arguments: "%{signer} benutzte das Schlüsselwort '%{keyword}' in einer Email an die Liste." key_management: deleted: "Gelöscht: %{key_string}" not_deletable: "Darf nicht gelöscht werden: %{key_string}" no_imports: In deiner Email konnten keine Schlüssel gefunden werden. :( key_import_status: imported: | Dieser Schlüssel wurde neu hinzugefügt: %{key_oneline} updated: | Dieser Schlüssel wurde aktualisiert: %{key_oneline} unchanged: | Dieser Schlüssel wurde nicht verändert: %{key_oneline} error: | Der Schlüssel mit diesem Fingerabdruck konnte aus unbekanntem Grund nicht hinzugefügt werden: %{fingerprint} matching_keys_intro: Alle Schlüssel aus dem Schlüsselring der Liste, die '%{input}' enthalten, sind an diese Email angehängt. delete_key_requires_arguments: | Fehler: Du hast zu dem Schlüsselwort 'DELETE-KEY' keinen Wert angegeben. Ein Wert ist nötig, weitere sind optional. Bspw.: X-DELETE-KEY: 0xB3D190D5235C74E1907EACFE898F2C91E2E6E1F3 Oder, um mehrere Schlüssel auf einmal zu löschen: X-DELETE-KEY: 0xB3D190D5235C74E1907EACFE898F2C91E2E6E1F3 a-subscription@hostname Die Schlüssel werden nur gelöscht, wenn sie der einzige Treffer für den jeweiligen Wert sind. fetch_key_requires_arguments: | Fehler: Du hast zu dem Schlüsselwort 'FETCH-KEY' keinen Wert angegeben. Ein Wert ist nötig, weitere sind optional. Jeder Wert kann eine URL sein, die via HTTP geladen wird, oder ein Text, mit dem auf den OpenPGP-Schlüsselserver gesucht wird. Bspw., um einen Schlüssel per fingerprint vom Schlüsselserver zu holen: X-FETCH-KEY: 0xB3D190D5235C74E1907EACFE898F2C91E2E6E1F3 Oder, um zwei Schlüssel per Email-Adresse vom Schlüsselserver zu holen: X-FETCH-KEY: a-subscription@hostname anotherone@example.org Oder, um einen Schlüssel per HTTP von einem Server zu laden: X-FETCH-KEY: https://example.org/keys/mykey.asc resend: not_resent_no_keys: Resending an <%{email}> fehlgeschlagen (%{all_keys} Schlüssel gefunden, davon %{usable_keys} nutzbar. Unverschlüsseltes Senden verboten). not_resent_encrypted_no_keys: Verschlüsseltes Resending an <%{email}> fehlgeschlagen (%{all_keys} Schlüssel gefunden, davon %{usable_keys} nutzbar). aborted: Resending an <%{email}> abgebrochen aufgrund anderer Probleme. encrypted_to: Verschlüsselt an unencrypted_to: Unverschlüsselt an invalid_recipient: "Ungültige Emailadresse für resend: %{address}" subscription_management: forbidden: "Fehler: Du bist nicht berechtigt, das Abo für %{email} zu löschen." is_not_subscribed: Kein Abo für %{email} gefunden. unsubscribed: Abo für %{email} wurde gelöscht. unsubscribing_failed: | Abo für %{email} nicht gelöscht: %{errors} cannot_unsubscribe_last_admin: | %{email} ist das einzige admin-Abo für diese Liste, daher kann es nicht gelöscht werden. subscribed: | Abo für %{email} mit diesen Werten eingetragen: Fingerabdruck: %{fingerprint} Admin? %{admin} Email-Zustellung aktiv? %{delivery_enabled} subscribing_failed: | Abo für %{email} nicht eingetragen: %{errors}. list_of_subscriptions: "Abos:\n" set_fingerprint_only_self: Nur admins dürfen den Fingerabdruck für andere Abos festlegen. fingerprint_set: Fingerabdruck für %{email} auf %{fingerprint} gesetzt. setting_fingerprint_failed: | Fingerabdruck für %{email} konnte nicht auf %{fingerprint} gesetzt werden: %{errors}. set_fingerprint_requires_valid_fingerprint: | Du hast zu dem Schlüsselwort 'SET-FINGERPRINT' keinen gültigen Wert angegeben. Es wurde der folgende Wert erkannt: %{fingerprint} Benötigt werden ein oder zwei Werte, bspw.: X-SET-FINGERPRINT: 0xB3D190D5235C74E1907EACFE898F2C91E2E6E1F3 oder (als admin): X-SET-FINGERPRINT: subscription2@hostname 0xB3D190D5235C74E1907EACFE898F2C91E2E6E1F3 Wobei der Fingerprint in der gesamten Länge (40 Zeichen) angegeben werden muss. Optional mit 0x als Präfix. Um einen Fingerprint zu entfernen kannst du das Schlüsselwort 'UNSET-FINGERPRINT' verwenden. set_fingerprint_requires_arguments: | Du hast zu dem Schlüsselwort 'SET-FINGERPRINT' keinen Wert angegeben. Benötigt werden ein oder zwei Werte, bspw.: X-SET-FINGERPRINT: 0xB3D190D5235C74E1907EACFE898F2C91E2E6E1F3 oder (als admin): X-SET-FINGERPRINT: subscription2@hostname 0xB3D190D5235C74E1907EACFE898F2C91E2E6E1F3 Um einen Fingerprint zu entfernen kannst du das Schlüsselwort 'UNSET-FINGERPRINT' verwenden. unset_fingerprint_only_self: Nur admins dürfen den Fingerabdruck für andere Abos festlegen. fingerprint_unset: Fingerabdruck für %{email} wurde entfernt. unsetting_fingerprint_failed: | Fingerabdruck für %{email} konnte nicht entfernt werden: %{errors}. unset_fingerprint_requires_arguments: | Du hast zu dem Schlüsselwort 'UNSET-FINGERPRINT' keinen Wert angegeben. Benötigt werden ein Wert, bspw.: X-UNSET-FINGERPRINT: subscription2@hostname Als admin musst du um deinen eigenen Fingerabdruck zu entfernen, noch zusätzlich das Argument force mitgeben. bspw.: X-UNSET-FINGERPRINT: adminsubscription2@hostname force subscribe_requires_arguments: | Fehler: Du hast zu dem Schlüsselwort 'SUBSCRIBE' keinen Wert angegeben. Mindestens ein Wert ist nötig, drei weitere sind optional. Bspw.: X-SUBSCRIBE: new-subscription@hostname Oder, um den Schlüssel für das neue Abo zuzuweisen: X-SUBSCRIBE: new-subscription@hostname 0xB3D190D5235C74E1907EACFE898F2C91E2E6E1F3 Oder, um den Schlüssel zuzuweisen, und das Abo zum admin zu machen: X-SUBSCRIBE: new-subscription@hostname 0xB3D190D5235C74E1907EACFE898F2C91E2E6E1F3 true Oder, um den Schlüssel zuzuweisen, das Abo zum admin zu machen, und die Zustellung von Listen-Emails für dieses Abo abzuschalten: X-SUBSCRIBE: new-subscription@hostname 0xB3D190D5235C74E1907EACFE898F2C91E2E6E1F3 true false Wenn du die optionalen Werte weglässt hat das Abo keinen Schlüssel zugewiesen, ist nicht admin, und hat die Zustellung von Listen-Email aktiviert. signatures_attached: Die Signaturen hängen an. list_management: no_logfile: Keine Log-Datei für %{listname} gefunden. (Das kann an einem hohem Log-Level und der Abwesenheit von Fehlern liegen.) logfile_attached: Die Log-Datei für %{listname} hängt an. list_public_key_subject: Schlüssel dieser Adresse list_public_key_attached: Der Schlüssel zu dieser Adresse hängt an. no_output_result: Deine Email ergab keinen Ausgabe-Text. owner_forward_prefix: Die folgende Email ging für die Listen-Besitzer/innen ein. no_keywords_error: Deine Email enthielt keine Schlüsselwörter, daher gab es nichts zu tun. missing_listname_keyword_error: Deine Email enthielt nicht das notwendige Schlüsselwort "X-LIST-NAME", daher wurde sie zurückgewiesen. wrong_listname_keyword_error: Deine Email enthielt ein falsches "X-LIST-NAME"-Schlüsselwort. Der Wert dieses Schlüsselworts muss der Emailadresse dieser Liste gleichen. bounces_drop_all: Die angehängte Email hätte zurückgewiesen (bounced) werden sollen, wurde aber stillschweigend fallen gelassen, weil die Konfiguration dieser Liste definiert, dass für diese Liste nie Email zurückgewiesen werden soll. bounces_drop_on_headers: "Die angehängte Email hätte zurückgewiesen (bounce) werden sollen, wurde aber stillschweigend fallen gelassen, weil diese Kopfzeile gefunden wurde: %{key}: %{value}" bounces_notify_admins: "Die angehängte Email wurde mit folgender Nachricht zurückgewiesen:" notice: Hinweis incoming_message: Eingehende Email forward_all_incoming_to_admins: Die angehängte Email ging ein. forward_automated_message_to_admins: Die angehängte Email wurde vermutlich von einer Maschine und nicht von einem Menschen versendet. Daher ist sie nicht über die Liste verteilt sondern an euch Admins weitergeleitet worden. automated_message_subject: Automatische Nachricht empfangen check_keys: Schlüsselprüfung check_keys_intro: "Bitte kümmere dich um die folgenden Schlüssel für Liste %{email}." key_expires: | Dieser Schlüssel läuft in %{days} Tagen ab: %{key_oneline} key_unusable: | Dieser Schlüssel ist %{usability_issue}: %{key_oneline} missed_message_due_to_unusable_key: "Du hast eine Email von %{list_email} verpasst weil mit deinem Abo kein (benutzbarer) OpenPGP-Schlüssel verknüpft ist. Bitte kümmere dich darum." refresh_keys: Schlüsselaktualisierung refresh_keys_intro: "Die Aktualisierung aller Schlüssel des Schlüsselrings für Liste %{email} ergab dies:" pin_keys: Schlüsselpinning pin_keys_intro: "Die Überprüfung aller Abos der Liste %{email} ergab, dass wir für folgende Abos einen Schlüssel zur Verwendung festgelegt haben:" key_updated: | Dieser Schlüssel wurde aktualisiert (%{states}): %{key_oneline} key_fetched: | Dieser Schlüssel wurde geholt (%{states}): %{key_oneline} import_states: unchanged: unverändert new_key: neuer Schlüssel new_uids: neue User-IDs new_subkeys: neue Unterschlüssel new_signatures: neue Signaturen fetch_key: invalid_input: "Ungültige Angabe. Gültig sind: URLs, OpenPGP-Fingerabdrücke, oder Emailadressen." pseudoheaders: scrubbed_message: Diese Email enthielt ungültige Zeichen, die aus Verarbeitungsgründen möglicherweise entfernt wurden. stripped_html_from_multialt: Diese Email enthielt einen alternativen HTML-Teil, der PGP-Daten beinhaltete. Der HTML-Teil wurde entfernt, um die Email sauberer analysieren zu können. stripped_html_from_multialt_with_keywords: Diese Email enthielt Schlüsselwörter und einen alternativen HTML-Teil. Der HTML-Teil wurde entfernt, um zu verhindern dass diese Schlüsselwörter Aussenstehenden bekannt werden. signature_states: unknown: "Unbekannte Signatur von unbekanntem Schlüssel 0x%{fingerprint}" unsigned: "Unsigniert" encryption_states: encrypted: "Verschlüsselt" unencrypted: "Unverschlüsselt" header_munging: "%{from} über %{list} <%{list_address}>" activerecord: errors: models: schleuder/subscription: attributes: email: taken: 'ist schon eingetragen' schleuder-3.6.0/locales/en.yml000066400000000000000000000341631401002544500162470ustar00rootroot00000000000000en: errors: attributes: language: inclusion: "must be one of: en, de" log_level: inclusion: "must be one of: debug, info, warn, error" openpgp_header_preference: inclusion: "must be one of: sign, encrypt, signencrypt, unprotected, none" internal_footer: invalid: "includes non-printable characters" public_footer: invalid: "includes non-printable characters" invalid_email: "is not a valid email address" invalid_fingerprint: "is not a valid OpenPGP-fingerprint" list_fingerprint_missing: "List has no fingerprint configured, cannot run! (In `%{listdir}`.)" list_key_missing: "List-key is missing in keyring, cannot run! (In `%{listdir}`.)" list_secret_key_missing: "Secret key of list is missing in keyring, cannot run! (In `%{listdir}`.)" list_admins_missing: "List has no admins configured, cannot run! (In `%{listdir}`.)" fatalerror: | A fatal error happened. Administrators have been notified. Please try again later. signoff: | Kind regards, Your Schleuder system. decryption_failed: | Decrypting your message failed. Messages to this address must be encrypted with the following key: %{key} To receive it send an email to <%{email}>. message_unsigned: Messages to this address must be OpenPGP-signed. message_signature_unknown: | Messages to this address must be OpenPGP-signed by the key that is configured for your subscription. If you don't know which one that is, ask an administrator of this list. You can contact the administrators by sending a message to <%{owner_email}> (preferably encrypt it with this addresses' public key: %{list_fingerprint}). message_unencrypted: Messages to this address must be encrypted conforming to OpenPGP. message_unauthenticated: Messages to this address must be encrypted and signed by the key associated with a subscribed address. message_sender_not_subscribed: Only subscribed addresses may send messages to this address. message_not_from_admin: Only admins may send messages to this address. message_empty: | Your message was found empty and wasn't passed on to the list. In case you only sent keywords please note that administrative keywords must be sent to the "request"-address (<%{request_address}>) in order to be respected. no_linebreaks: "must not include line-breaks" list_not_found: "Error: No list found with this address: '%{email}'." invalid_characters: "contains invalid characters" listdir_problem: message: "There's a problem with the list-directory: '%{dir}' %{problem}." not_existing: does not exist not_a_directory: is not a directory not_empty: is not empty not_writable: is not writable not_readable: is not readable keyword_admin_only: The keyword '%{keyword}' may only be used by list-admin. key_generation_failed: Generating the OpenPGP key pair for %{listname} failed for unknown reasons. Please check the list-directory ('%{listdir}') and the log-files. key_adduid_failed: "Adding a user-ID to the OpenPGP key failed with this message:\n%{errmsg}" too_many_keys: "Error: In %{listdir} there's more than one matching OpenPGP-key for %{listname}. Please delete all but one." loading_list_settings_failed: "%{config_file} could not be parsed, please check its formatting to be valid YAML." message_too_big: "Your message was too big. Allowed are up to %{allowed_size}KB." must_be_boolean: "must be true or false" must_be_greater_than_zero: "must be a number greater than zero" not_pgp_mime: "Message was not encrypted in the pgp/mime-format." delivery_error: "The following error occurred while sending a message to %{email}: %{error}" no_match_for: "No match found for %{input}" too_many_matching_keys: | Too many matching keys for '%{input}': %{key_strings} plugins: unknown_keyword: Unknown keyword '%{keyword}'. plugin_failed: Running keyword '%{keyword}' caused an unknown error. System-admins have been notified. keyword_admin_notify_request: "%{signer} sent the keyword '%{keyword}' with the values '%{arguments}' and received this response:" keyword_admin_notify_request_without_arguments: "%{signer} sent the keyword '%{keyword}' and received this response:" keyword_admin_notify_lists: "%{signer} used the keyword '%{keyword}' with the values '%{arguments}' in a message sent to the list." keyword_admin_notify_lists_without_arguments: "%{signer} used the keyword '%{keyword}' in a message sent to the list." key_management: deleted: | This key was deleted: %{key_string} not_deletable: | This key may not be deleted: %{key_string} no_imports: In the message you sent us, no keys could be found. :( key_import_status: imported: | This key was newly added: %{key_oneline} updated: | This key was updated: %{key_oneline} unchanged: | This key was not changed: %{key_oneline} error: | The key with this fingerprint could not be added due to an unknown error: %{fingerprint} matching_keys_intro: All keys from the list's keyring matching '%{input}' are attached to this message. delete_key_requires_arguments: | Error: You did not send any arguments for the keyword 'DELETE-KEY'. One is required, more are optional, e.g.: X-DELETE-KEY: 0xB3D190D5235C74E1907EACFE898F2C91E2E6E1F3 Or, to delete multiple keys at once: X-DELETE-KEY: 0xB3D190D5235C74E1907EACFE898F2C91E2E6E1F3 a-subscription@hostname The matching keys will be deleted only if the argument matches them distinctly. fetch_key_requires_arguments: | Error: You did not send any arguments for the keyword 'FETCH-KEY'. One is required, more are optional. Each argument can be an URL to fetch via HTTP, or a string to look up at the OpenPGP-keyservers. E.g., to fetch a key by fingerprint from the keyserver: X-FETCH-KEY: 0xB3D190D5235C74E1907EACFE898F2C91E2E6E1F3 Or, to fetch two keys by email-address from the keyserver: X-FETCH-KEY: a-subscription@hostname anotherone@example.org Or, to fetch a key keys by URL: X-FETCH-KEY: https://example.org/keys/mykey.asc resend: not_resent_no_keys: Resending to <%{email}> failed (%{all_keys} keys found, of which %{usable_keys} can be used. Unencrypted sending not allowed). not_resent_encrypted_no_keys: Resending as encrypted email to <%{email}> failed (%{all_keys} keys found, of which %{usable_keys} can be used). aborted: Resending to <%{email}> aborted due to other errors. encrypted_to: Encrypted to unencrypted_to: Unencrypted to invalid_recipient: "Invalid email-address for resending: %{address}" subscription_management: forbidden: "Error: You're not allowed to unsubscribe %{email}." is_not_subscribed: "%{email} is not subscribed." unsubscribed: "%{email} has been unsubscribed." unsubscribing_failed: | Unsubscribing %{email} failed: %{errors} cannot_unsubscribe_last_admin: | %{email} is the only admin for this list, thus it can not be unsubscribed. subscribed: | %{email} has been subscribed with these attributes: Fingerprint: %{fingerprint} Admin? %{admin} Email-delivery enabled? %{delivery_enabled} subscribing_failed: | Subscribing %{email} failed: %{errors}. list_of_subscriptions: "Subscriptions:\n" set_fingerprint_only_self: Only admins may set fingerprints of subscriptions other than their own. fingerprint_set: Fingerprint for %{email} set to %{fingerprint}. setting_fingerprint_failed: | Setting fingerprint for %{email} to %{fingerprint} failed: %{errors}. set_fingerprint_requires_valid_fingerprint: | You did not send a valid fingerprint for the keyword 'SET-FINGERPRINT' The following value was detected: %{fingerprint} One or two are required, e.g.: X-SET-FINGERPRINT: 0xB3D190D5235C74E1907EACFE898F2C91E2E6E1F3 or (as an admin): X-SET-FINGERPRINT: subscription2@hostname 0xB3D190D5235C74E1907EACFE898F2C91E2E6E1F3 While the fingerprint must be passed in the full length (40 characters). Optionally prefixed with 0x. To remove a fingerprint you can use the keyword 'UNSET-FINGERPRINT' set_fingerprint_requires_arguments: | Error: You did not send any arguments for the keyword 'SET-FINGERPRINT'. One or two are required, e.g.: X-SET-FINGERPRINT: 0xB3D190D5235C74E1907EACFE898F2C91E2E6E1F3 or (as an admin): X-SET-FINGERPRINT: subscription2@hostname 0xB3D190D5235C74E1907EACFE898F2C91E2E6E1F3 To remove a fingerprint you can use the keyword 'UNSET-FINGERPRINT' unset_fingerprint_only_self: Only admins may remove fingerprints of subscriptions other than their own. unset_fingerprint_requires_arguments: | Error: You did not send any arguments for the keyword 'UNSET-FINGERPRINT' One value is required, e.g.: X-UNSET-FINGERPRINT: subscription2@hostname As an admin to unset your own fingerprint you must additionally pass the argument force. E.g.: X-UNSET-FINGERPRINT: adminsubscription2@hostname force fingerprint_unset: Fingerprint for %{email} removed. unsetting_fingerprint_failed: | Removing fingerprint for %{email} failed: %{errors}. subscribe_requires_arguments: | Error: You did not send any arguments for the keyword 'SUBSCRIBE'. At least one argument is required, three more are optional. E.g.: X-SUBSCRIBE: new-subscription@hostname Or, defining the key to use for the new subscription: X-SUBSCRIBE: new-subscription@hostname 0xB3D190D5235C74E1907EACFE898F2C91E2E6E1F3 Or, defining the key to use, and setting this subscription to be an admin: X-SUBSCRIBE: new-subscription@hostname 0xB3D190D5235C74E1907EACFE898F2C91E2E6E1F3 true Or, defining the key to use, setting this subscription as admin, and disabling the delivery of list-emails to this subscription: X-SUBSCRIBE: new-subscription@hostname 0xB3D190D5235C74E1907EACFE898F2C91E2E6E1F3 true false If you omit the optional arguments, the subscription has no key assigned, is not an admin, and has the delivery of list-emails enabled. signatures_attached: Find the signatures attached. list_management: no_logfile: No logfile could be found for %{listname}. (This might be caused by a high log-level and the absence of errors.) logfile_attached: The logfile for %{listname} is attached. list_public_key_subject: Key for this address list_public_key_attached: Find the key for this address attached. no_output_result: Your message resulted in no output. owner_forward_prefix: The following message was received for the list-owners. no_keywords_error: Your message didn't contain any keywords, thus there was nothing to do. missing_listname_keyword_error: Your message did not contain the required "X-LIST-NAME" keyword and was rejected. wrong_listname_keyword_error: Your message contained an incorrect "X-LIST-NAME" keyword. The keyword argument must match the email address of this list. bounces_drop_all: The attached message should have been bounced but was dropped without further notice because the list's configuration defines that no message should ever be bounced. bounces_drop_on_headers: "The attached message should have been bounced but was dropped without further notice because it matched this header-line: %{key}: %{value}" bounces_notify_admins: "The attached message was bounced with the following notice:" notice: Notice incoming_message: Incoming message forward_all_incoming_to_admins: The attached message was received. forward_automated_message_to_admins: Attached is a message that probably was sent by a machine, not a human. Therefore it has not been passed on to the list, but only to you, the admins. automated_message_subject: Automated message received check_keys: Keys check check_keys_intro: "Please take care of these keys for list %{email}." key_expires: | This key expires in %{days} days: %{key_oneline} key_unusable: | This key is %{usability_issue}: %{key_oneline} missed_message_due_to_unusable_key: "You missed an email from %{list_email} because your subscription isn't associated with a (usable) OpenPGP key. Please fix this." refresh_keys: Keys update refresh_keys_intro: "Refreshing all keys from the keyring of list %{email} resulted in this:" pin_keys: Keys pinning pin_keys_intro: "While checking all subscriptions of list %{email} we were pinning a matching key for the following subscriptions:" key_updated: | This key was updated (%{states}): %{key_oneline} key_fetched: | This key was fetched (%{states}): %{key_oneline} import_states: unchanged: unchanged new_key: new key new_uids: new user-IDs new_subkeys: new subkeys new_signatures: new signatures fetch_key: invalid_input: "Invalid input. Allowed are: URLs, OpenPGP-fingerprints, or email-addresses." pseudoheaders: scrubbed_message: This message included invalid characters, which might have been removed to be able to process the message properly. stripped_html_from_multialt: This message included an alternating HTML-part that contained PGP-data. The HTML-part was removed to enable parsing the message more properly. stripped_html_from_multialt_with_keywords: This message included keywords and an alternating HTML-part. The HTML-part was removed to prevent the disclosure of these keywords to third parties. signature_states: unknown: "Unknown signature by unknown key 0x%{fingerprint}" unsigned: "Unsigned" encryption_states: encrypted: "Encrypted" unencrypted: "Unencrypted" header_munging: "%{from} via %{list} <%{list_address}>" activerecord: errors: models: schleuder/subscription: attributes: email: taken: 'is already subscribed' schleuder-3.6.0/man/000077500000000000000000000000001401002544500142445ustar00rootroot00000000000000schleuder-3.6.0/man/schleuder-api-daemon.8000066400000000000000000000033451401002544500203300ustar00rootroot00000000000000.\" generated with Ronn/v0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3 . .TH "SCHLEUDER\-API\-DAEMON" "8" "January 2017" "" "" . .SH "NAME" \fBschleuder\-api\-daemon\fR \- provides the API of schleuder(8) . .SH "SYNOPSIS" \fBschleuder\-api\-daemon\fR . .SH "DESCRIPTION" schleuder\-api\-daemon provides the HTTP\-API of \fBschleuder(8)\fR to clients\. . .SH "ENVIRONMENT" . .SS "Configuration" \fBschleuder\-api\-daemon\fR reads configuration out of the \fBapi\fR section of \fBschleuder\fR\'s configuration\. Please see \fBschleuder\fR(8) for details about the configuration file\. . .P The available options are: . .TP \fBhost\fR The hostname/IP to listen at\. . .TP \fBport\fR The port to listen at\. Default: 4443\. . .TP \fBtls_cert_file\fR Path to the file that contains the TLS\-certificate to use\. You can generate a new one with \fBschleuder cert generate\fR\. . .TP \fBtls_key_file\fR Path to the file that contains the TLS\-key to use\. . .TP \fBvalid_api_keys\fR List of api_keys to allow access to the API\. . .SS "Clients" Available clients using the API are \fBschleuder\-cli\fR(8) and \fBschleuder\-web\fR\. URLs to their websites are listed below (\fISEE ALSO\fR)\. . .SH "BUGS" Known bugs are listed on the Schleuder bugtracker at \fIhttps://0xacab\.org/schleuder/schleuder\fR . .SH "SEE ALSO" \fBschleuder\fR(8), \fBschleuder\-cli\fR(8) . .TP Website of \fBschleuder\fR \fIhttps://schleuder\.org/\fR . .TP More extensive documentation for \fBschleuder\fR \fIhttps://schleuder\.org/docs/\fR . .TP \fBschleuder\-cli\fR, the command line interface for list\-management \fIhttps://0xacab\.org/schleuder/schleuder\-cli/\fR . .TP \fBschleuder\-web\fR, the web interface for list\-management \fIhttps://0xacab\.org/schleuder/schleuder\-web/\fR schleuder-3.6.0/man/schleuder-api-daemon.8.ron000066400000000000000000000027701401002544500211260ustar00rootroot00000000000000schleuder-api-daemon(8) -- provides the API of schleuder(8) =========================================================== ## SYNOPSIS `schleuder-api-daemon` ## DESCRIPTION schleuder-api-daemon provides the HTTP-API of `schleuder(8)` to clients. ## ENVIRONMENT ### Configuration `schleuder-api-daemon` reads configuration out of the `api` section of `schleuder`'s configuration. Please see `schleuder`(8) for details about the configuration file. The available options are: * `host`: The hostname/IP to listen at. * `port`: The port to listen at. Default: 4443. * `tls_cert_file`: Path to the file that contains the TLS-certificate to use. You can generate a new one with `schleuder cert generate`. * `tls_key_file`: Path to the file that contains the TLS-key to use. * `valid_api_keys`: List of api_keys to allow access to the API. ### Clients Available clients using the API are `schleuder-cli`(8) and `schleuder-web`. URLs to their websites are listed below ([SEE ALSO][]). ## BUGS Known bugs are listed on the Schleuder bugtracker at ## SEE ALSO `schleuder`(8), `schleuder-cli`(8) * Website of `schleuder`: * More extensive documentation for `schleuder`: * `schleuder-cli`, the command line interface for list-management: * `schleuder-web`, the web interface for list-management: schleuder-3.6.0/man/schleuder.8000066400000000000000000000143511401002544500163170ustar00rootroot00000000000000.\" generated with Ronn/v0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3 . .TH "SCHLEUDER" "8" "January 2017" "" "" . .SH "NAME" \fBschleuder\fR \- an email hub for groups . .SH "SYNOPSIS" \fBschleuder\fR work \fIlistaddress\fR < \fIemail\fR . .P \fBschleuder\fR help . .P \fBschleuder\fR \fIother\-command\fR [<\.\.\.>] . .P For descriptions of the other commands see the output of the \fIhelp\fR\-command\. . .P This manual page is written for system administrators\. For other information please read the Schleuder documentation online (\fISEE ALSO\fR)\. . .SH "DESCRIPTION" Schleuder is an email hub for groups\. Subscribers can communicate encryptedly and pseudonymously among themselves, receive emails from non\-subscribers and send emails to non\-subscribers via the list\. . .P Schleuder takes care of all de\- and encryption, stripping of headers, formatting conversions, etc\. Further Schleuder can send out its own public key and receive administrative commands by email\. . .P Email cryptography is handled by using GnuPG\. . .SH "ENVIRONMENT" . .SS "Configuration" Schleuder reads its basic settings from a file that it by default expects at \. To make Schleuder read a different file set the environment variable \fISCHLEUDER_CONFIG\fR to the path to your file when running schleuder\. E\.g\.: . .IP "" 4 . .nf SCHLEUDER_CONFIG=/usr/local/etc/schleuder\.yml /path/to/bin/schleuder \.\.\. . .fi . .IP "" 0 . .P For explanations of the possible settings read the default config file\. . .P The default settings for new lists are read from another config file\. By default Schleuder looks at \. To make Schleuder read a different file set the environment variable \fISCHLEUDER_LIST_DEFAULTS\fR analogous to above\. The possible settings are explained in the default config file\. . .SS "Connect to MTA" Schleuder behaves like an email\-filter: it reads email from standard\-input, and reports errors to standard\-error\. If all goes well Schleuder closes the initial connection to the Mail Transport Agent (MTA) only after it sent out all outgoing emails\. . .P In case of an error the MTA is expected to include Schleuder\'s error message into a bounce\-email that is sent back to the sender (this is default behaviour of most MTAs)\. . .P To connect the MTA with Schleuder it must pipe the incoming message into Schleuder\'s STDIN, and give it two arguments: first one: "work", second one: the full recipients email address\. . .P For more information on how to integrate Schleuder with your existing mail setup, please read the Schleuder documentation online (\fISEE ALSO\fR)\. . .SS "Data storage" The keyrings for each list are standard GnuPG keyrings and sit in the filesystem under \fIlists_dir\fR/\fIhostname\fR/\fIlistname\fR/ (\fIlists_dir\fR is read from schleuder\.yml, by default it is )\. They can be used manually using gpg2\. Please be careful to maintain proper file permissions if you touch the files\. . .P In the list\-directory there’s also a list specific log\-file (might be missing if the log\-level is high and no error occurred yet)\. . .P Other logging is sent to syslog\. Where that ends up depends on the operating system and the system administration\. . .P All other list\-related data is stored in the SQL\-database\. Most data is unserialized, only some values are JSON\-encoded\. . .SH "SPECIAL FEATURES" Schleuder features some special functionality\. For more detailed information read the Schleuder documentation online (\fISEE ALSO\fR)\. . .SS "Getting the public key of a list" Each Schleuder\-list replies with its public key to any email sent to \fIlistname\-sendkey@hostname\fR\. E\.g\. to receive the key for the contact address of the Schleuder project write an email to . .br \fIteam\-sendkey@schleuder\.org\fR\. . .SS "Email commands" Schleuder knows some special keywords that trigger different behaviour\. You can e\.g\. subscribe someone, or resend an email to a non\-subscriber using keywords\. . .P Keywords require that: . .IP "\(bu" 4 they start the line and begin with "x\-", . .IP "\(bu" 4 they are written into the beginning of the \fIfirst text\-part\fR of the email (usually that’s just the normal body of the email), . .IP "\(bu" 4 possible arguments must be written \fIon the same line\fR as the keyword (exceptions are mentioned in the descriptions below), . .IP "\(bu" 4 the email must be \fIencrypted and signed\fR by a list\-member’s key\. . .IP "" 0 . .P Keywords can be repeated within one email at will\. Letter case doesn’t matter\. . .P There are two types of keywords: those to enhance messages sent over the list (“list\-keywords”), and those to request something from Schleuder (“request\-keywords”)\. . .P Find detailed descriptions of all available keywords in the Schleuder documentation online (\fISEE ALSO\fR)\. . .SS "Contact list\-owner" Write to \fIlistname\-owner@hostname\fR to contact the list\-owner(s) even if you don\'t know who they are\. Use the list\'s key to encrypt the email! . .SH "EXIT STATUS" . .TP 0 Incoming email was processed without errors\. . .TP 1 Internal failure in incoming email processing\. . .SH "FILES" . .IP "\(bu" 4 \fB/etc/schleuder/schleuder\.yml\fR: default path of global Schleuder configuration . .IP "\(bu" 4 \fB/etc/schleuder/list\-defaults\.yml\fR: default path of default list settings . .IP "\(bu" 4 \fB/var/lib/schleuder/lists\fR default path of lists_dir . .IP "\(bu" 4 \fB\fR/\fB\fR/`\fIlistname\fR: list internal data . .IP "\(bu" 4 \fB\fR/\fB\fR/\fB\fR/list\.log`: log\-file for list . .IP "" 0 . .P All configuration files are formatted as YAML\. See \fIhttp://www\.yaml\.org/\fR for more details\. . .SH "BUGS" Known bugs are listed on the Schleuder bugtracker at \fIhttps://0xacab\.org/schleuder/schleuder\fR . .SH "SEE ALSO" \fBschleuder\-cli\fR(8), \fBgnupg\fR(7)\. . .TP Website of \fBschleuder\fR \fIhttps://schleuder\.org/\fR . .TP More extensive documentation for \fBschleuder\fR \fIhttps://schleuder\.org/docs/\fR . .TP \fBschleuder\-cli\fR, the command line interface for list\-management \fIhttps://0xacab\.org/schleuder/schleuder\-cli/\fR . .TP \fBschleuder\-web\fR, the web interface for list\-management \fIhttps://0xacab\.org/schleuder/schleuder\-web/\fR schleuder-3.6.0/man/schleuder.8.ron000066400000000000000000000131771401002544500171210ustar00rootroot00000000000000schleuder(8) -- an email hub for groups ======================================= ## SYNOPSIS `schleuder` work < `schleuder` help `schleuder` [<...>] For descriptions of the other commands see the output of the -command. This manual page is written for system administrators. For other information please read the Schleuder documentation online ([SEE ALSO][]). ## DESCRIPTION Schleuder is an email hub for groups. Subscribers can communicate encryptedly and pseudonymously among themselves, receive emails from non-subscribers and send emails to non-subscribers via the list. Schleuder takes care of all de- and encryption, stripping of headers, formatting conversions, etc. Further Schleuder can send out its own public key and receive administrative commands by email. Email cryptography is handled by using GnuPG. ## ENVIRONMENT ### Configuration Schleuder reads its basic settings from a file that it by default expects at . To make Schleuder read a different file set the environment variable to the path to your file when running schleuder. E.g.: SCHLEUDER_CONFIG=/usr/local/etc/schleuder.yml /path/to/bin/schleuder ... For explanations of the possible settings read the default config file. The default settings for new lists are read from another config file. By default Schleuder looks at . To make Schleuder read a different file set the environment variable analogous to above. The possible settings are explained in the default config file. ### Connect to MTA Schleuder behaves like an email-filter: it reads email from standard-input, and reports errors to standard-error. If all goes well Schleuder closes the initial connection to the Mail Transport Agent (MTA) only after it sent out all outgoing emails. In case of an error the MTA is expected to include Schleuder's error message into a bounce-email that is sent back to the sender (this is default behaviour of most MTAs). To connect the MTA with Schleuder it must pipe the incoming message into Schleuder's STDIN, and give it two arguments: first one: "work", second one: the full recipients email address. For more information on how to integrate Schleuder with your existing mail setup, please read the Schleuder documentation online ([SEE ALSO][]). ### Data storage The keyrings for each list are standard GnuPG keyrings and sit in the filesystem under /// ( is read from schleuder.yml, by default it is ). They can be used manually using gpg2. Please be careful to maintain proper file permissions if you touch the files. In the list-directory there’s also a list specific log-file (might be missing if the log-level is high and no error occurred yet). Other logging is sent to syslog. Where that ends up depends on the operating system and the system administration. All other list-related data is stored in the SQL-database. Most data is unserialized, only some values are JSON-encoded. ## SPECIAL FEATURES Schleuder features some special functionality. For more detailed information read the Schleuder documentation online ([SEE ALSO][]). ### Getting the public key of a list Each Schleuder-list replies with its public key to any email sent to . E.g. to receive the key for the contact address of the Schleuder project write an email to
. ### Email commands Schleuder knows some special keywords that trigger different behaviour. You can e.g. subscribe someone, or resend an email to a non-subscriber using keywords. Keywords require that: * they start the line and begin with "x-", * they are written into the beginning of the *first text-part* of the email (usually that’s just the normal body of the email), * possible arguments must be written *on the same line* as the keyword (exceptions are mentioned in the descriptions below), * the email must be *encrypted and signed* by a list-member’s key. Keywords can be repeated within one email at will. Letter case doesn’t matter. There are two types of keywords: those to enhance messages sent over the list (“list-keywords”), and those to request something from Schleuder (“request-keywords”). Find detailed descriptions of all available keywords in the Schleuder documentation online ([SEE ALSO][]). ### Contact list-owner Write to to contact the list-owner(s) even if you don't know who they are. Use the list's key to encrypt the email! ## EXIT STATUS * 0: Incoming email was processed without errors. * 1: Internal failure in incoming email processing. ## FILES * `/etc/schleuder/schleuder.yml`: default path of global Schleuder configuration * `/etc/schleuder/list-defaults.yml`: default path of default list settings * `/var/lib/schleuder/lists` default path of lists_dir * ``/``/`: list internal data * ``/``/``/list.log`: log-file for list All configuration files are formatted as YAML. See for more details. ## BUGS Known bugs are listed on the Schleuder bugtracker at ## SEE ALSO `schleuder-cli`(8), `gnupg`(7). * Website of `schleuder`: * More extensive documentation for `schleuder`: * `schleuder-cli`, the command line interface for list-management: * `schleuder-web`, the web interface for list-management: schleuder-3.6.0/schleuder.gemspec000066400000000000000000000062731401002544500170240ustar00rootroot00000000000000# encoding: utf-8 $: << File.expand_path('../lib', __FILE__) require 'schleuder/version' Gem::Specification.new do |s| s.name = "schleuder" s.version = Schleuder::VERSION s.authors = 'schleuder dev team' s.email = "team@schleuder.org" s.homepage = "https://schleuder.org/" s.summary = "Schleuder is a gpg-enabled mailing list manager with remailing-capabilities." s.description = "Schleuder is a group's email-gateway: subscribers can exchange encrypted emails among themselves, receive emails from non-subscribers and send emails to non-subscribers via the list.\n\n(Please note: For some platforms there's a better way of installing Schleuder than `gem install`. See for details.)" s.files = `git ls-files lib locales etc db README.md Rakefile bin/pinentry-clearpassphrase`.split s.executables = %w[schleuder schleuder-api-daemon] s.platform = Gem::Platform::RUBY s.require_path = 'lib' # TODO: extend/replace expired cert #s.signing_key = "#{ENV['HOME']}/.gem/schleuder-gem-private_key.pem" #s.cert_chain = ['gem-public_cert.pem'] s.license = 'GPL-3.0' s.metadata = { "homepage_uri" => "https://schleuder.org/", "documentation_uri" => "https://schleuder.org/docs/", "changelog_uri" => "https://0xacab.org/schleuder/schleuder/blob/master/CHANGELOG.md", "source_code_uri" => "https://0xacab.org/schleuder/schleuder/", "bug_tracker_uri" => "https://0xacab.org/schleuder/schleuder/issues", "mailing_list_uri" => "https://lists.nadir.org/mailman/listinfo/schleuder-announce/", } s.required_ruby_version = ">= 2.1.0" # Explicitly depend on BigDecimal 1.4, because later versions are # incompatible with activesupport 4.2, which is a dependency of activerecord 4.2. if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('2.7.0') s.add_runtime_dependency 'bigdecimal', '~> 1.4' end s.add_runtime_dependency 'gpgme', '~> 2.0', '>= 2.0.19' # Explicitly include to force a version. s.add_runtime_dependency 'mail', '~> 2.7.1' s.add_runtime_dependency 'mail-gpg', '~> 0.3', '< 0.4.3' s.add_runtime_dependency 'activerecord', '~> 4.2' # TODO: Drop this once we cease to support ruby 2.1, see #310 s.add_runtime_dependency 'rack-test', '~> 0.7.0' s.add_runtime_dependency 'rake', '>= 10.5.0' s.add_runtime_dependency 'sqlite3', '~> 1.3.6' s.add_runtime_dependency 'sinatra', '~> 1' s.add_runtime_dependency 'sinatra-contrib', '~> 1' s.add_runtime_dependency 'thor', '~> 0' s.add_runtime_dependency 'thin', '~> 1' s.add_runtime_dependency 'charlock_holmes', '~> 0.7.6' s.add_development_dependency 'rspec', '~> 3.5.0' s.add_development_dependency 'hirb' s.add_development_dependency 'factory_bot' s.add_development_dependency 'database_cleaner' s.add_development_dependency 'simplecov-console' if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('2.6.0') s.add_development_dependency 'irb' end s.post_install_message = " Please consider additionally installing schleuder-cli (allows to configure lists from the command line). To set up Schleuder on this system please run `schleuder install`. " end schleuder-3.6.0/spec/000077500000000000000000000000001401002544500144235ustar00rootroot00000000000000schleuder-3.6.0/spec/factories/000077500000000000000000000000001401002544500164025ustar00rootroot00000000000000schleuder-3.6.0/spec/factories/lists.rb000066400000000000000000000031161401002544500200660ustar00rootroot00000000000000FactoryBot.define do factory :list do sequence(:email) {|n| "list#{n}@example.org" } fingerprint { "59C71FB38AEE22E091C78259D06350440F759BD3" } log_level { "warn" } subject_prefix { nil } subject_prefix_in { nil } subject_prefix_out { nil } openpgp_header_preference { "signencrypt" } internal_footer { nil } public_footer { nil } headers_to_meta { ["from", "to", "cc", "date", "sig", "enc"] } bounces_drop_on_headers { { "x-spam-flag" => true } } keywords_admin_only { ["subscribe", "unsubscribe", "delete-key"] } keywords_admin_notify { ["add-key"] } send_encrypted_only { true } receive_encrypted_only { false } receive_signed_only { false } receive_authenticated_only { false } receive_from_subscribed_emailaddresses_only { false } receive_admin_only { false } keep_msgid { true } bounces_drop_all { false } bounces_notify_admins { true } deliver_selfsent { true } include_autocrypt_header { true } include_list_headers { true } include_openpgp_header { true } max_message_size_kb { 10240 } language { "en" } forward_all_incoming_to_admins { false } logfiles_to_keep { 2 } after(:build) do |list| FileUtils.mkdir_p(list.listdir) gpghome_upstream = File.join "spec", "gnupg" FileUtils.cp_r Dir["#{gpghome_upstream}/{private*,*.gpg,.*migrated}"], list.listdir end trait :with_one_subscription do after(:build) do |list| create(:subscription) end end factory :list_with_one_subscription, traits: [:with_one_subscription] end end schleuder-3.6.0/spec/factories/subscriptions.rb000066400000000000000000000003561401002544500216420ustar00rootroot00000000000000FactoryBot.define do factory :subscription do list sequence(:email) {|n| "subscription#{n}@example.org" } fingerprint { "129A74AD5317457F9E502844A39C61B32003A8D8" } admin { true } delivery_enabled { true } end end schleuder-3.6.0/spec/fixtures/000077500000000000000000000000001401002544500162745ustar00rootroot00000000000000schleuder-3.6.0/spec/fixtures/bla_foo_key.txt000066400000000000000000000031741401002544500213130ustar00rootroot00000000000000-----BEGIN PGP PUBLIC KEY BLOCK----- mQENBEudENYBCADPG94KbqEUQSv3yKbn7Oh/ky0Wn0QTgeTAB/T+oP5au9I/5CnS /Rgd8M4k4n/g9orPDfZ1kp3G0sMphLs5XFh9rdtk4iZUVDdU20nfB1lHGMZreGfv mhWyYs7GlitFPHGhJUSdQ6kmxR5MjnfE8S+nXYVWkthHxaU21NIkXGyGWcTCc4ML 8BbJAsgZt2QCWE+l4OO04GoLJtttug8a2RqAuzGHit2+yc8Zv9HAwUjexrw+KZhI TnTOiT4aF5XZmVJyPYAaksjKtAXbkR7nWDWi4yTTm6VFEN6Jpajk3CEqBuyFJW+Y +60oXjf8ktwughxiV5IJCljlDoX1BDPJXw7XABEBAAG0EGJsYWJsYSA8YmxhQGZv bz6JATgEEwECACIFAkudENYCGwMGCwkIBwMCBhUIAgkKCwQWAgMBAh4BAheAAAoJ EOvb6JklHyQSklQH/iavy1ercHoF7VI71b9iSrRHvlYDEnwED9y3p2ZNtOiR3dBX 6/vFErWoLnaIRSXfsUMnMtJxuxIwu0xCXmGxzzXqX1HFjZk6ofG7eajL/JC+ugAg 0ZNsHHBrBfgaWypyO7QSZyZDlEog7Yk6/Dji1fv0RZsqKo4kF+Fc5HsUyw7yN22K yjCjdu+KCgnMA6D1GLG++AirWnWxQW1CCqykuzXIMy2Z040zu8q9hv/m4m+0IXuS eFCkcrN2taP3bY+Ynn8r2X6ZV9xhMOJ13ylqn7hCebH1QsGxfIN2mfFesrUbuLb4 9KSr0qQBkYG81xOfBemCAJNu5pzQBGebgp9siX65AQ0ES50Q1gEIAMx0UKr+H63b XRhB+R/Ipn6njz3YnEAUhMYUgZueeh5MRwf1CJXXPdJ0avWRdbD689T0qhuwHMw0 iAebRxPOTzdbaUiNzXlS+9kfJu/AEbRFJPo1MgiDJr73lLpMWHUxWHSRC/OSoSYA /AHBriTorxaWpmc7A1rfdC13sVPq87TRX8MLhRXOlEiryD+AeM4rmWvBWZiljPuT Oa7dQBkO5USYkkiamlkfHaBGEfFdiWVBP6XIFiixFDUL1BKsImhpyht59aLb4Bar hIxft17xPmoDNVOGj3k0/xkFJEv6N7btB8I5DfcjdOZ3CYd8Orprm+dZPajnZeaS 8sde5ngjTZcAEQEAAYkBHwQYAQIACQUCS50Q1gIbDAAKCRDr2+iZJR8kEizPB/4x xcvm29isTIoVEtEXNkzs589YHarVKNnB1rbBRyB+p/mhdhjb7zVSIPrGrwss0kzC i00sHYr3a70MbKfM8fAoFr2d9ikoUVfBl1tVxCNH+6FYxp8g1vcNmcTMfsArFnFi 2MQOrnJNkUatAuprAouOLEApiGgTy6QikVpsxYPUT+BXHTP/vKW+fg/rJq87ub2v IuhwdI04saTRDj7jYzQsTWDVmwaTd3zcov8H9EL7DGUudZxi3t4kFfOwqBzbQ/fH fOGFBWOe1xM7EmdS0Gplss1pAnY+MuSicD0/j7/tWn7wJelMuTXxczSHM+4Vs/Yw 86SvVJhKa3G/1UCnzzzp =trkO -----END PGP PUBLIC KEY BLOCK----- schleuder-3.6.0/spec/fixtures/broken_utf8_uid_key.txt000066400000000000000000000032101401002544500227700ustar00rootroot00000000000000-----BEGIN PGP PUBLIC KEY BLOCK----- mQGiBD4tUP0RBADyrM6g52fnEgXryP54M2R+2AXcyXo6qEd7ZXzqoh9myckJ3gLS DsS7Og/TOev8w3h5ZHmFvDgWBZjzcqg0DGC17pSyBvOx8Byhz6Wd6U7YibxjpBuS /N+WMm5xEjlJVV1SJvNzMSxD5rVOprA61DgfsbW6ScAMk3VDW7jxLcG05wCg/ynJ j/vdowhlqjPJIlSZK49mQfcD/0IhBgd4M4SxxUWQNUdhm7GMXuC2pxqhqnKoSMM7 zmndGPOlf29Xn7Zc3mW8LUvaz2HmJyztMqk0F3qfNTPXEUu8OvyheN5vFNwysF2O zE8wSv8LcyH4GVxwNUSSy3dxcKfJfIoLOpmJ7TZjJ5rkPkYg5UpOlTohAW8EhPSW KU+RA/sH/h8wVdQclBJ3IxJylZ0sk2OyEbaobmGtJbch8Yqo/cbYhprmDKgE6L3h e4cKan78NTr+g7q4O+enHkkql7PW91aormHpCIDd8q01wcbvcdnjsgS4adESq/Eb p8ZZj5itaOslJWvqvyi4j2X0c1hXXHG0MxMvyOIHPHgU4krnd7Q5QvxuZG5pcyBB bGxlIGdlZ2VuIFJlY2h0cyA8aW5mb0BidWVuZG5pcy1nZWdlbi1yZWNodHMuY2g+ iFgEEBECABgFAj4tUP0ICwMJCAcCAQoCGQEFGwMAAAAACgkQEkL24T2OvkqbBwCg wQ2rPbHxPqVU36HTIOr9pKbU5YgAmgK4sDjlS7naIy7Yg6u0q9UcNRtSuQINBD4t UP0QCAD2Qle3CH8IF3KiutapQvMF6PlTETlPtvFuuUs4INoBp1ajFOmPQFXz0AfG y0OplK33TGSGSfgMg71l6RfUodNQ+PVZX9x2Uk89PY3bzpnhV5JZzf24rnRPxfx2 vIPFRzBhznzJZv8V+bv9kV7HAarTW56NoKVyOtQa8L9GAFgr5fSI/VhOSdvNILSd 5JEHNmszbDgNRR0PfIizHHxbLY7288kjwEPwpVsYjY67VYy4XTjTNP18F1dDox0Y bN4zISy1Kv884bEpQBgRjXyEpwpy1obEAxnIByl6ypUM2Zafq9AKUJsCRtMIPWak XUGfnHy9iUsiGSa6q6Jew1XpMgs7AAICB/95aHF6jqhYsbsyFGm7YKeSWFUjy1Hh LJMnrfsY043xZqfwiXyDeNT5xAInN6YibUFIU+xCu5zdtknEfUiI1/nMK3pWkYgQ 3xwyJPTpboidcLucinYQejz4Nx14p5/Lv/jpmYlAesjy/t/QINXzDn/BeoOwyOtY 8AxL++X0M95UcNOqvWaXthTBtsGYAxoCvpzmxaHagqw90FYvjGHL5PymCCOHpZZ3 GfL10lc16nUFvetqhZTP3+hG6I5VQi8sHvcULgodLHSM2gkfu8gvcsYbyNZNRKrS WqLC0/pPhkQGNGPLC3uUlBC2tGMS1iWiIOODiDl3brW61FmEBGP1qFl9iEwEGBEC AAwFAj4tUP0FGwwAAAAACgkQEkL24T2OvkorgQCgkMFb92w+01OAABwrjGCIW97h W0UAn3D/PPbXYP0uo3sDOePOqeOv0ls7 =Q88o -----END PGP PUBLIC KEY BLOCK----- schleuder-3.6.0/spec/fixtures/default_list_key.txt000066400000000000000000000060121401002544500223630ustar00rootroot00000000000000-----BEGIN PGP PUBLIC KEY BLOCK----- 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 /J2/tBYro55u =lep5 -----END PGP PUBLIC KEY BLOCK----- schleuder-3.6.0/spec/fixtures/example_key.txt000066400000000000000000000060441401002544500213440ustar00rootroot00000000000000-----BEGIN PGP PUBLIC KEY BLOCK----- Version: GnuPG/MacGPG2 v2 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 gpCMrbUUdX4= =H2Gw -----END PGP PUBLIC KEY BLOCK----- schleuder-3.6.0/spec/fixtures/expired_key.txt000066400000000000000000000032201401002544500213420ustar00rootroot00000000000000-----BEGIN PGP PUBLIC KEY BLOCK----- mQENBExlilkBCACb2AQyclf7latAIE1kCTfKQ9jmcKyf959ymyhzoeNmBDpKjILC 7MOXtICo/V/xAzhWBK/vT9+56brGUBTugnW3yK+zllQprI3kIYaRS1SrbmKVwVse 9qLVUL1BssohFaEeQqT4MNh62ziJymqCguGEGXpYlEqzEDTmmhTANiPKRBZDrdfq 3FU3OJUMTGzuG34mKmXMRr0azprF228LUujMMKyWhG1hxh3El04C4jPuMSbaVcwN E2rgIg8jaNAQuSyXkaprPZ8/nRG8UFGRtCMEIEh6Ou6KybF1NI9LQKCwcsGcLHKU 2u/8vOCExxdwl9Jjlqmof4FQV7bT++6SC0n3ABEBAAG0EWV4cGlyZWQgPGJsYUBm b28+iQE+BBMBAgAoBQJMZYpZAhsDBQkAAVGABgsJCAcDAgYVCAIJCgsEFgIDAQIe AQIXgAAKCRD3Gj+EEtg4iV6yB/4uDLoN1+TswtGjpUlu2CyjHe7pb05dAU4sWfTV I+fxBuyEo+cf/23nOeoGyltBDR0heSg3TIfXQrbWD4WoVsOXPaT0fq6UEzeadkmn A5NN3PGkv46o3ZSF1ltkY9ybMgnmRLHYCojSu5bSBMRVyurr0ozwNRPtFUTka8Lj wxiwDJ394D5y6PjL56FPkUdKydzFGV2ptSKsqyAJvMBeGlQ4I6TpiBx0Lz2A1Qn+ 4uXgTVPqgalC5YKTTTjOfQcieOOeqtI0LHqDpS/DIPLnwTUCN8OL2TQIeDudm3YI P8FCKvImh840vTbpgFSgQeaJzJFv9UrloNyyvbVtaeoxnxoBuQENBExlilkBCADD Gbf0TEs5HDpbUC78tJetGWipmQRTq8gS9dDoKjG5mvlpFARPTAJvewgI7DICXMtV Y8P8eFbsZDGMETduunadutDvyP9J/wuknYHJkE5jJeZjEKyofrWM1BHxHb2bkNU0 hr8EVNvEhVjAb62cJPj5emi/3UhynLoJrrO+AZSr9Bq2QW38ntSUxTXM7VbGUR1M WZSoJ+gEg/IeR2HJziCyb1mhlvo9pZqJT959bNVQ/xU4NHtYca5cV3X88Ald4Dwz 2HM+PIBbsiz3C3fIMNrRxRvMCU4PgsjSZFoRxcdDRT5OjBxNgQ4UmWQH0sTFw9Tx 8B2OtwuguGwaXIV3FpRDABEBAAGJASUEGAECAA8FAkxlilkCGwwFCQABUYAACgkQ 9xo/hBLYOImqngf/QQt0S6tlJ9OMknmAr2pNg+DQkCqTNaSk/iQj4leGGwkpRVoH 5VFTZ0nkmZjcDTTrCjj5rEDaRo8Q38KsB1po8P25ABoK0b28rHw8I3L2Byl1+IB7 +dNKVyFJVfHAYOQsbI/p/2KdtZZIbpxnRVHY+Vlu2p/fx3JqPmqCiaVMcUFw55Qj SKaI+omfnN0WGyrK1Rub925Lch0vZkxVwmTse7qufg0iwTREMy9VZfMavMhkAtM2 AsiEG8j3mwU9JQfBkXqtWxG2VvtsBJ0rLafh5sR3NgjtR2vbSdzJRCV2xO4z6Drh 3Pug3ReHmcLUFTDPE+vmeH+xpEZ2nhvNRFDhmQ== =Nao0 -----END PGP PUBLIC KEY BLOCK----- schleuder-3.6.0/spec/fixtures/expired_key_extended.txt000066400000000000000000000033421401002544500232270ustar00rootroot00000000000000-----BEGIN PGP PUBLIC KEY BLOCK----- Version: SKS 1.1.6+ Comment: Hostname: sks.spodhuis.org mQENBExlilkBCACb2AQyclf7latAIE1kCTfKQ9jmcKyf959ymyhzoeNmBDpKjILC7MOXtICo /V/xAzhWBK/vT9+56brGUBTugnW3yK+zllQprI3kIYaRS1SrbmKVwVse9qLVUL1BssohFaEe QqT4MNh62ziJymqCguGEGXpYlEqzEDTmmhTANiPKRBZDrdfq3FU3OJUMTGzuG34mKmXMRr0a zprF228LUujMMKyWhG1hxh3El04C4jPuMSbaVcwNE2rgIg8jaNAQuSyXkaprPZ8/nRG8UFGR tCMEIEh6Ou6KybF1NI9LQKCwcsGcLHKU2u/8vOCExxdwl9Jjlqmof4FQV7bT++6SC0n3ABEB AAG0EWV4cGlyZWQgPGJsYUBmb28+iQFVBBMBAgA/AhsDBgsJCAcDAgYVCAIJCgsEFgIDAQIe AQIXgBYhBJh2nooQkfNr2IQD7PcaP4QS2DiJBQJYgOG1BQkMHGNXAAoJEPcaP4QS2DiJxiUH /2xYCT+mldoaWMyJlBleSjx0wtWeGNayMuv0RjU2pIkBmslYp/ZZkt+JC3thpJneBW5pJuRB qeUi7yTigdtOrH47g+FfIDCY89ymTDbYW4vpNnnsV7s+ke8tbEmTtMpjFypoTvbnGYlq8VLz 87eRcsLwADOAJfFBdnDD0tyNCrUY/V+Ti/ZI4bHoFA14t8Hm7MIDkfB6sVfzpnZd1ACj+klv 1rfq+9m56lsavS/dM+BlhwfRORT9cenuBs++AXXWvh1CZW/J06kFECG+ptqU5246nQcjE5GX W8sC+TSq7OXSTQAJDF+aWqjA/JrbpSf/3r2/IU+mGH2Bwi7B5uBN6lG5AQ0ETGWKWQEIAMMZ t/RMSzkcOltQLvy0l60ZaKmZBFOryBL10OgqMbma+WkUBE9MAm97CAjsMgJcy1Vjw/x4Vuxk MYwRN266dp260O/I/0n/C6SdgcmQTmMl5mMQrKh+tYzUEfEdvZuQ1TSGvwRU28SFWMBvrZwk +Pl6aL/dSHKcugmus74BlKv0GrZBbfye1JTFNcztVsZRHUxZlKgn6ASD8h5HYcnOILJvWaGW +j2lmolP3n1s1VD/FTg0e1hxrlxXdfzwCV3gPDPYcz48gFuyLPcLd8gw2tHFG8wJTg+CyNJk WhHFx0NFPk6MHE2BDhSZZAfSxMXD1PHwHY63C6C4bBpchXcWlEMAEQEAAYkBJQQYAQIADwUC TGWKWQIbDAUJAAFRgAAKCRD3Gj+EEtg4iaqeB/9BC3RLq2Un04ySeYCvak2D4NCQKpM1pKT+ JCPiV4YbCSlFWgflUVNnSeSZmNwNNOsKOPmsQNpGjxDfwqwHWmjw/bkAGgrRvbysfDwjcvYH KXX4gHv500pXIUlV8cBg5Cxsj+n/Yp21lkhunGdFUdj5WW7an9/Hcmo+aoKJpUxxQXDnlCNI poj6iZ+c3RYbKsrVG5v3bktyHS9mTFXCZOx7uq5+DSLBNEQzL1Vl8xq8yGQC0zYCyIQbyPeb BT0lB8GReq1bEbZW+2wEnSstp+HmxHc2CO1Ha9tJ3MlEJXbE7jPoOuHc+6DdF4eZwtQVMM8T 6+Z4f7GkRnaeG81EUOGZ =4p8E -----END PGP PUBLIC KEY BLOCK----- schleuder-3.6.0/spec/fixtures/expiring_key.txt000066400000000000000000000033511401002544500215340ustar00rootroot00000000000000-----BEGIN PGP PUBLIC KEY BLOCK----- mQENBFmCxIEBCADUiLMwu7I/EuyyNlidrllyVt2GkXVwSa1yIR3nA1KyDqizspih SL4eVaZOvVWyJaGxIFbmG5WHCQi0YuuDv0jcGYT3lmyPumrDYyaU5GHm05gmZ+R4 +oSjJG/v5z7L6au2G/+Iw5pQg819VviJ6po+QwmQeUkHd7xhiniPq7aoVFcoltgE bQF8sPWJ1jyFnTmL36MECgAP9MKPfcSuHzUWJxiDSo8Siqaf7uUY7F2Gz9pBYuiv g6PJqnagtjZGPgxKqQak/IRvPjk6WWIGpaO9fBl1GQ/W3iuhkObBWuHNdErygQX8 0VDc/wRfIeFsMjaPQ/nQOALgzsTGZWpdO/T9ABEBAAG0JmV4cGlyaW5nIGtleSA8 ZXhwaXJpbmdrZXlAZXhhbXBsZS5vcmc+iQFUBBMBCAA+FiEEQh+/cZBkATZ4hZPN num+WSnKzCAFAlmCxIECGwMFCSWYBgAFCwkIBwIGFQgJCgsCBBYCAwECHgECF4AA CgkQnum+WSnKzCBnQwgAmCy016/VxvLHSZ45TuYO60dGfrmu6nA3/F2qKjXsszlw UL+7jiFZZzLRQF8GJGnHJnhg6mCz8yQKam8pOqaYCqVvc19GyzPdQ22uiOA0QcuE 0kHd/ncAEtRJ3q+yeb7rcxVlHDHx2VpzNY3d2aRsgSYin+iAWKROUt3efZyTquzJ etOl6SvbwTv+qqDmrEj/zNQmr1Dic+KtLvK8ClyXrfZou5wCGsX14fKk7xkhNPBS f2oCaPjMjGsh9gZ+nZfpv+ppTAbZRPSKHuQrWksFGGxDTMigQORNtwA2SBljmL63 neqajK086P3U3dZm4lD4dPCG/V2VVYgLsooCzJZUYbkBDQRZgsSBAQgAx9bBVzuv AlLbPIqHyXsjurosvoolUKAjdWFaGCK1lZHdy3RwuVVdgWA7qXpr/T6sQ0OzxaK/ HT/1G0haCKd3zC2dD3FUQJHzIPXqE4x36a+PF/qq2vVe43+8Lwz2ceopHprHP7Sx anqnagiV/JQNJna7WTk4RM/61oHiBNWyusEhW2vynTs92ltEL4Esh3BKpyQ6mmV+ DLGalraMSDcuGRzwQMTlRrXygxq2WHc9px3M3PfMBSj86ouhSOkwOPI3eV4XPzB+ uXxwcZTsUxPm8BVVt5OAmrLaaX2K/AWEsZlVdSJpZrFD2WMMo3YRKrwvM8AHhuQO FJKaHPibi+a3zwARAQABiQE8BBgBCAAmFiEEQh+/cZBkATZ4hZPNnum+WSnKzCAF AlmCxIECGwwFCSWYBgAACgkQnum+WSnKzCAwMAf+L5ZFRTgha0AKnmWTR7JA2weg EPPDt33AHZFOCYcxuHm8TPgl4OuSvoxxWovCm56/nIiWnqojNVlWCQxAHHQmC1dA xJ7EDqdqCqVvRyRCzUsONICKeHdAoNA7TWw/DF+JZn2l+ud2w+EiQt9qy3sQXZeG SOG6s5kSPxxuwPmmMmCu5u+QI4elcHaw9RLGFbwlO4VlBS/n0k6P+UDY/4Eqkyi0 L7GCFtw3ZKjRR24MKYdGRbv7hpzvp6JyrbYA9H4wGJir43Dk/EH7Ul+4Y8FcHFk4 FU9yPzi0dW07tKD29F0GxRdqtIs0rWHIbUJVskDwDhJdteIsO/bTuKN4tZvtcQ== =c/Mw -----END PGP PUBLIC KEY BLOCK----- schleuder-3.6.0/spec/fixtures/filters/000077500000000000000000000000001401002544500177445ustar00rootroot00000000000000schleuder-3.6.0/spec/fixtures/filters/post_decryption/000077500000000000000000000000001401002544500231715ustar00rootroot00000000000000schleuder-3.6.0/spec/fixtures/filters/post_decryption/75_post_example.rb000066400000000000000000000001111401002544500265220ustar00rootroot00000000000000module Schleuder::Filters def self.post_example(list, mail) end end schleuder-3.6.0/spec/fixtures/filters/pre_decryption/000077500000000000000000000000001401002544500227725ustar00rootroot00000000000000schleuder-3.6.0/spec/fixtures/filters/pre_decryption/25_example.rb000066400000000000000000000001041401002544500252530ustar00rootroot00000000000000module Schleuder::Filters def self.example(list, mail) end end schleuder-3.6.0/spec/fixtures/filters/pre_decryption/invalid_filter_file.rb000066400000000000000000000001111401002544500273020ustar00rootroot00000000000000module Schleuder::Filters def self.never_show_up(list, mail) end end schleuder-3.6.0/spec/fixtures/filters_without_pre/000077500000000000000000000000001401002544500223755ustar00rootroot00000000000000schleuder-3.6.0/spec/fixtures/filters_without_pre/post_decryption/000077500000000000000000000000001401002544500256225ustar00rootroot00000000000000schleuder-3.6.0/spec/fixtures/filters_without_pre/post_decryption/05_post_example.rb000066400000000000000000000001071401002544500311510ustar00rootroot00000000000000module Schleuder::Filters def self.post_example(list,mail) end end schleuder-3.6.0/spec/fixtures/mails/000077500000000000000000000000001401002544500174015ustar00rootroot00000000000000schleuder-3.6.0/spec/fixtures/mails/attach-list-key-thunderbird.eml000066400000000000000000000061561401002544500254230ustar00rootroot00000000000000From: user To: testlist@example.net Message-ID: <6ce92946-85f0-075a-3577-ab5f6420d389@example.net> Date: Sat, 4 Jan 2020 19:43:54 +0100 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Thunderbird/68.3.1 MIME-Version: 1.0 Subject: ... Content-Type: multipart/encrypted; protocol="application/pgp-encrypted"; boundary="1JxyxqJLgO8VkVyQcZm0f2mqBg2sGa75c" This is an OpenPGP/MIME encrypted message (RFC 4880 and 3156) --1JxyxqJLgO8VkVyQcZm0f2mqBg2sGa75c Content-Type: application/pgp-encrypted Content-Description: PGP/MIME version identification Version: 1 --1JxyxqJLgO8VkVyQcZm0f2mqBg2sGa75c Content-Type: application/octet-stream; name="encrypted.asc" Content-Description: OpenPGP encrypted message Content-Disposition: inline; filename="encrypted.asc" -----BEGIN PGP MESSAGE----- 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 725O30U= =2AyW -----END PGP MESSAGE----- --1JxyxqJLgO8VkVyQcZm0f2mqBg2sGa75c-- schleuder-3.6.0/spec/fixtures/mails/big_first_mime_part.txt000066400000000000000000000643421401002544500241600ustar00rootroot00000000000000Content-Type: multipart/mixed; boundary="NrllqtU3K9aakndDUX4Wq60iXnCpR3rT4"; protected-headers="v1" From: foo To: list1@lists.example.net Message-ID: Subject: My protected subject References: In-Reply-To: --NrllqtU3K9aakndDUX4Wq60iXnCpR3rT4 Content-Type: multipart/alternative; boundary="------------030809040800070509090406" This is a multi-part message in MIME format. --------------030809040800070509090406 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable foobar lg >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> Cc:=20 >>>>>> >>>>>> >>>>>> >>>>>> >> > --------------030809040800070509090406 Content-Type: text/html; charset=utf-8 Content-Transfer-Encoding: quoted-printable foorbar
lg

Am 23.11.2017 um 11:51 schrieb foobar@lists.example.net:



Am 23.11.2017 um 09:44 schrieb foobar@li= sts.example.net:
=
From: bbaauunn <bbaauunn@=
example.com>

To: foobar@lists.example.net

Cc:=20

true" class=3D"moz-txt-link-rfc2396E" href=3D"mailto:bbaauunn@example.com"=
><bbaauunn@example.com>

Enc: Encrypted



hey,






Am 22.11.2017 um 19:03 schrieb <= a class=3D"moz-txt-link-abbreviated" href=3D"mailto:foobar@lists.example.net" moz-do-not-send=3D"true">foobar@lists.example.net= :
From: bbaauunn <utop=
ia11@example.com>







To: foobar@lists.example.net







Cc:=20














true" class=3D"moz-txt-link-rfc2396E" href=3D"mailto:bbaauunn@example.com"=
><bbaauunn@example.com>







Enc: Encrypted









br>

To: foobar@lists.example.net Cc:=20 Enc: Encrypted

































































































































































From: bbaauunn <=
bbaauunn@example.com>
















              

              
Cc:=20
















              
















              

              
Enc: Encrypted
















              

              

              

              

              

              

              
hey!
















              
















              
















              
















              
















              
















              
lg
















              

              

              

              

              

              

              
To: 
















              
Cc:=20
















              
















              

              
Enc: Encrypted
















              

                

              

                

              

                

              

                

              
















              

                

              
















              

                

              
















              
















              
















              

                

              

              

              

              
Cc:=20
















              
















              

              
Enc: Encrypted
















              

                  

              

                  

              

                  

              
















              
















              
















              

                  

              

                  

              

              

              

              
Cc:=20
















              
0
















              

              
Enc: Encrypted
















              

                    

              

                    

              

                    

              

                    

              
















              
















              
















              

                    

              
















              
















              
















              

                    

              
















              

                    

              
LG
















              

                  

              

              

              

              

            





--------------030809040800070509090406-- --NrllqtU3K9aakndDUX4Wq60iXnCpR3rT4-- schleuder-3.6.0/spec/fixtures/mails/bounce.eml000066400000000000000000000114501401002544500213540ustar00rootroot00000000000000Received: by schleuder.example.org with local (Exim 4.87) id 1dOBwu-0005qF-LI for schleuder@example.org; Fri, 23 Jun 2017 00:00:00 +0200 X-Failed-Recipients: paz@nadir.org Auto-Submitted: auto-replied From: Mail Delivery System To: schleuder@example.org Content-Type: multipart/report; report-type=delivery-status; boundary=1498175744-eximdsn-1404350378 MIME-Version: 1.0 Subject: Mail delivery failed: returning message to sender Message-Id: Date: Fri, 23 Jun 2017 01:55:44 +0200 --1498175744-eximdsn-1404350378 Content-type: text/plain; charset=us-ascii This message was created automatically by mail delivery software. A message that you sent could not be delivered to one or more of its recipients. This is a permanent error. The following address(es) failed: paz@nadir.org host 127.0.0.1 [127.0.0.1] SMTP error from remote mail server after RCPT TO:: 450 4.7.1 : Recipient address rejected: Sorry, your message cannot be delivered to that person because their mailbox is full. If you can contact them another way, you may wish to tell them of this problem: retry timeout exceeded --1498175744-eximdsn-1404350378 Content-type: message/delivery-status Reporting-MTA: dns; schleuder.example.org Action: failed Final-Recipient: rfc822;paz@nadir.org Status: 5.0.0 Remote-MTA: dns; 127.0.0.1 Diagnostic-Code: smtp; 450 4.7.1 : Recipient address rejected: Sorry, your message cannot be delivered to that person because their mailbox is full. If you can contact them another way, you may wish to tell them of this problem: retry timeout exceeded --1498175744-eximdsn-1404350378 Content-type: message/rfc822 Received: from [IPv6:::1] (localhost.localdomain [IPv6:::1]) by flutsch.local (Postfix) with ESMTP id 1DCDC801DD for ; Thu, 29 Dec 2016 15:09:43 +0100 (CET) From: schleuder@example.org To: paz@nadir.org Subject: bounce test Message-ID: Date: Thu, 29 Dec 2016 15:09:29 +0100 MIME-Version: 1.0 Content-Type: multipart/encrypted; protocol="application/pgp-encrypted"; boundary="V4nVnp5nddnPgg4bACDcs1kSu5wBuHpL9" This is an OpenPGP/MIME encrypted message (RFC 4880 and 3156) --V4nVnp5nddnPgg4bACDcs1kSu5wBuHpL9 Content-Type: application/pgp-encrypted Content-Description: PGP/MIME version identification Version: 1 --V4nVnp5nddnPgg4bACDcs1kSu5wBuHpL9 Content-Type: application/octet-stream; name="encrypted.asc" Content-Description: OpenPGP encrypted message Content-Disposition: inline; filename="encrypted.asc" -----BEGIN PGP MESSAGE----- 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 =eXeI -----END PGP MESSAGE----- --V4nVnp5nddnPgg4bACDcs1kSu5wBuHpL9-- --1498175744-eximdsn-1404350378-- schleuder-3.6.0/spec/fixtures/mails/bounces/000077500000000000000000000000001401002544500210375ustar00rootroot00000000000000schleuder-3.6.0/spec/fixtures/mails/bounces/malformed_bounce_01.txt.eml000066400000000000000000000054361401002544500261650ustar00rootroot00000000000000Return-Path: <> Received: by 10.216.28.198 with SMTP id g48cs228780wea; Wed, 16 Dec 2009 02:45:14 +0000 Received: ; Wed, 16 Dec 2009 02:41:20 +0000 Date: Wed, 16 Dec 2009 02:41:20 +0000 From: bounce@rediffmail.com To: support@myswom.com Message-Id: <4b2849b9.a813f30a.6c53.6801SMTPIN_ADDED@mx.google.com> Subject: failure notice Mime-Version: 1.0 Content-Type: multipart/mixed; boundary=mimepart_4b2849cc52ad8_16153fb6b5e769bc586b3 Authentication-Results: mx.google.com; spf=pass (google.com: domain of rediffmail.com designates 119.252.147.126 as permitted sender) smtp.mail= Delivered-To: support@myswom.com Received-Spf: pass (google.com: domain of rediffmail.com designates 119.252.147.126 as permitted sender) client-ip=119.252.147.126; --mimepart_4b2849cc52ad8_16153fb6b5e769bc586b3 Hi. This is the qmail-send program at rediffmail.com. I'm afraid I wasn't able to deliver your message to the following addresses. This is a permanent error; I've given up. Sorry it didn't work out. : - Sorry, no mailbox here by that name. (#5.1.1)Z --- Enclosed is a copy of the message. --mimepart_4b2849cc52ad8_16153fb6b5e769bc586b3 Content-Type: message/rfc822 Return-Path: Received: (qmail 43430 invoked from network); 16 Dec 2009 02:41:20 -0000 X-CNFS-Analysis: score=0 v=1.0 c=1 a=UP0woeyT68oA:10 a=8sBYAydLBaTw9O9PPbvJRQ==:17 a=nOXXgcrqAAAA:8 a=hpnyz_ZHDEhns6bXdMYA:9 a=lOoBsn5VqPa6SSdm1A8A:7 a=n6XhW81lUO9q5u5E7SHj76VjDTMA:4 a=abhB7gKK_5kA:10 a=4phKvQ69a4IA:10 X-REDIFF-SENDER-VERIFY: D=-2, P=D Received: from mail.swom.com (HELO xenon.swom.com) (188.40.35.30) by 0 with SMTP; 16 Dec 2009 02:41:20 -0000 Received: from myswom.com (xenon.swom.com [188.40.35.28]) (Authenticated sender: support@myswom.com) by xenon.swom.com (Postfix) with ESMTPSA id 64B392C60B for ; Wed, 16 Dec 2009 02:43:55 +0000 (GMT) Date: Wed, 16 Dec 2009 02:43:55 +0000 From: Cash Culture To: mithlesh_pm@rediffmail.com Message-Id: <4b28496b5a963_3adb3fc543c451b0910ee@xenon.swom.com.tmail> Subject: Cash Culture added you as a friend on Swom... Mime-Version: 1.0 Content-Type: text/plain; charset=utf-8 X-Swom-Uuid: 5c18dfcdfee13aa969f4c0c805e5ed0402b8f49b Cash has joined Swom.com and indicated you are a Friend: I'd like to add you to my wealth network on Swom. We know each other from CashCulture a while ago. - CashCulture To accept or view this invitation from Cash Culture: http://swom.com/c/7113/p/cdf64ba2/r/34007 What is Swom.com? ------------------- Swom.com is the new social networking site for professionals and business owners. It helps you make more money by rapidly expanding your wealth network and increasing your income. It's free to join and it's growing fast. The Swom.com Team --mimepart_4b2849cc52ad8_16153fb6b5e769bc586b3--schleuder-3.6.0/spec/fixtures/mails/bounces/tt_1234175799.txt.eml000066400000000000000000000051111401002544500241600ustar00rootroot00000000000000From MAILER-DAEMON Mon Feb 9 12:36:39 2009 Return-Path: <> X-Original-To: bounces-main+agris.ameriks=amerimailzzz.lv@amerimail.lv Delivered-To: bounce_and_mail_handler@ameriks Received: from Albanis-3.local (unknown [213.175.111.87]) by ameriks (Postfix) with ESMTP id 7888A3A1B1 for ; Mon, 9 Feb 2009 12:36:39 +0200 (EET) Received: by Albanis-3.local (Postfix) id 4242E326BA6; Mon, 9 Feb 2009 12:36:39 +0200 (EET) Date: Mon, 9 Feb 2009 12:36:39 +0200 (EET) From: MAILER-DAEMON@Albanis-3.local (Mail Delivery System) Subject: Undelivered Mail Returned to Sender To: bounces-main+agris.ameriks=amerimailzzz.lv@amerimail.lv Auto-Submitted: auto-replied MIME-Version: 1.0 Content-Type: multipart/report; report-type=delivery-status; boundary="34F80326BA4.1234175799/Albanis-3.local" Message-Id: <20090209103639.4242E326BA6@Albanis-3.local> This is a MIME-encapsulated message. --34F80326BA4.1234175799/Albanis-3.local Content-Description: Notification Content-Type: text/plain; charset=us-ascii This is the mail system at host Albanis-3.local. I'm sorry to have to inform you that your message could not be delivered to one or more recipients. It's attached below. For further assistance, please send mail to postmaster. If you do so, please include this problem report. You can delete your own text from the attached returned message. The mail system : Host or domain name not found. Name service error for name=amerimailzzz.lv type=A: Host not found --34F80326BA4.1234175799/Albanis-3.local Content-Description: Delivery report Content-Type: message/delivery-status Reporting-MTA: dns; Albanis-3.local X-Postfix-Queue-ID: 34F80326BA4 X-Postfix-Sender: rfc822; bounces-main@amerimail.lv Arrival-Date: Mon, 9 Feb 2009 12:36:39 +0200 (EET) Final-Recipient: rfc822; agris.ameriks@amerimailzzz.lv Action: failed Status: 5.4.4 Diagnostic-Code: X-Postfix; Host or domain name not found. Name service error for name=amerimailzzz.lv type=A: Host not found --34F80326BA4.1234175799/Albanis-3.local Content-Description: Undelivered Message Content-Type: message/rfc822 Received: by Albanis-3.local (Postfix, from userid 501) id 34F80326BA4; Mon, 9 Feb 2009 12:36:39 +0200 (EET) Date: Mon, 9 Feb 2009 12:36:33 +0200 From: ameriks@amerimail.lv Reply-To: ginta.amerika@ameri.lv To: agris.ameriks@amerimailzzz.lv Subject: subjecting Mime-Version: 1.0 Content-Type: text/html; charset=utf-8 Message-Id: <20090209103639.34F80326BA4@Albanis-3.local> Hello from mars! --34F80326BA4.1234175799/Albanis-3.local-- schleuder-3.6.0/spec/fixtures/mails/bounces/tt_1234177688.txt.eml000066400000000000000000000051771401002544500241730ustar00rootroot00000000000000From MAILER-DAEMON Mon Feb 9 13:08:08 2009 Return-Path: <> X-Original-To: bounces-main+aaaaagggrrriiiizz=inbox.lv@amerimail.lv Delivered-To: bounce_and_mail_handler@ameriks Received: from Albanis-3.local (unknown [213.175.111.87]) by ameriks (Postfix) with ESMTP id 904D93A1B1 for ; Mon, 9 Feb 2009 13:08:08 +0200 (EET) Received: by Albanis-3.local (Postfix) id 56B1E326DAB; Mon, 9 Feb 2009 13:08:08 +0200 (EET) Date: Mon, 9 Feb 2009 13:08:08 +0200 (EET) From: MAILER-DAEMON@Albanis-3.local (Mail Delivery System) Subject: Undelivered Mail Returned to Sender To: bounces-main+aaaaagggrrriiiizz=inbox.lv@amerimail.lv Auto-Submitted: auto-replied MIME-Version: 1.0 Content-Type: multipart/report; report-type=delivery-status; boundary="313F2326DA9.1234177688/Albanis-3.local" Message-Id: <20090209110808.56B1E326DAB@Albanis-3.local> This is a MIME-encapsulated message. --313F2326DA9.1234177688/Albanis-3.local Content-Description: Notification Content-Type: text/plain; charset=us-ascii This is the mail system at host Albanis-3.local. I'm sorry to have to inform you that your message could not be delivered to one or more recipients. It's attached below. For further assistance, please send mail to postmaster. If you do so, please include this problem report. You can delete your own text from the attached returned message. The mail system : host b.mx.inbox.lv[89.111.3.74] said: 554 5.7.1 : Recipient address rejected: Nonexistent user (in reply to RCPT TO command) --313F2326DA9.1234177688/Albanis-3.local Content-Description: Delivery report Content-Type: message/delivery-status Reporting-MTA: dns; Albanis-3.local X-Postfix-Queue-ID: 313F2326DA9 X-Postfix-Sender: rfc822; bounces-main@amerimail.lv Arrival-Date: Mon, 9 Feb 2009 13:08:07 +0200 (EET) Final-Recipient: rfc822; aaaaagggrrriiiizz@inbox.lv Action: failed Status: 5.7.1 Remote-MTA: dns; b.mx.inbox.lv Diagnostic-Code: smtp; 554 5.7.1 : Recipient address rejected: Nonexistent user --313F2326DA9.1234177688/Albanis-3.local Content-Description: Undelivered Message Content-Type: message/rfc822 Received: by Albanis-3.local (Postfix, from userid 501) id 313F2326DA9; Mon, 9 Feb 2009 13:08:07 +0200 (EET) Date: Mon, 9 Feb 2009 13:07:59 +0200 From: ameriks@amerimail.lv Reply-To: ginta.amerika@ameri.lv To: aaaaagggrrriiiizz@inbox.lv Subject: subjecting Mime-Version: 1.0 Content-Type: text/html; charset=utf-8 Message-Id: <20090209110807.313F2326DA9@Albanis-3.local> Hello from mars! --313F2326DA9.1234177688/Albanis-3.local-- schleuder-3.6.0/spec/fixtures/mails/bounces/tt_1234210655.txt.eml000066400000000000000000000114741401002544500241460ustar00rootroot00000000000000From MAILER-DAEMON Mon Feb 9 22:17:35 2009 Return-Path: <> X-Original-To: bounces-main+this_doesnotexistinAAc=accenture.com@amerimail.lv Delivered-To: bounce_and_mail_handler@ameriks Received: from amrmr1003.accenture.com (amrmr1003.accenture.com [170.252.248.72]) by ameriks (Postfix) with ESMTPS id D31BD3A08C for ; Mon, 9 Feb 2009 22:17:30 +0200 (EET) Received: from AMRXV1001.dir.svc.accenture.com (amrxv1001.dir.svc.accenture.com [10.10.160.61]) by amrmr1003.accenture.com (8.13.8/8.13.8) with ESMTP id n19KHDRY022245 for ; Mon, 9 Feb 2009 14:17:19 -0600 (CST) Received: from mtahm1100.accenture.com ([10.10.100.240]) by AMRXV1001.dir.svc.accenture.com with Microsoft SMTPSVC(6.0.3790.1830); Mon, 9 Feb 2009 14:17:00 -0600 X-BigFish: vps9(zzzzzzz2dh6bh43j68o) X-Spam-TCS-SCL: 7:0 X-MS-Exchange-Organization-Antispam-Report: OrigIP: 87.99.72.11;Service: EHS Date: Mon, 9 Feb 2009 22:15:33 +0200 From: Postmaster@accenture.com Reply-To: ginta.amerika@ameri.lv To: ameriks@amerimail.lv Subject: DELIVERY FAILURE: User this_doesnotexistinAAc (this_doesnotexistinAAc@accenture.com) not listed in public Name & Address Book Mime-Version: 1.0 Message-Id: <20090209201600.E1D7B328DAA@Albanis-3.local> X-OriginalArrivalTime: 09 Feb 2009 20:16:12.0664 (UTC) FILETIME=[40DC5F80:01C98AF3] X-MIMETrack: Itemize by SMTP Server on MTAHM1100/Server/Accenture(Release 5.0.9a |January 7, 2002) at 02/09/2009 02:16:57 PM, Serialize by Router on MTAHM1100/Server/Accenture(Release 5.0.9a |January 7, 2002) at 02/09/2009 02:16:58 PM, Serialize complete at 02/09/2009 02:16:58 PM Content-Type: multipart/report; report-type=delivery-status; boundary="==IFJRGLKFGIR48542UHRUHIHD" --==IFJRGLKFGIR48542UHRUHIHD Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit Your message Subject: subjecting was not delivered to: this_doesnotexistinAAc@accenture.com because: User this_doesnotexistinAAc (this_doesnotexistinAAc@accenture.com) not listed in public Name & Address Book --==IFJRGLKFGIR48542UHRUHIHD Content-Type: message/delivery-status Reporting-MTA: dns;mtahm1100.accenture.com Final-Recipient: rfc822;this_doesnotexistinAAc@accenture.com Action: failed Status: 5.1.1 Diagnostic-Code: X-Notes; User this_doesnotexistinAAc (this_doesnotexistinAAc@accenture.com) not listed in public Name & Address Book --==IFJRGLKFGIR48542UHRUHIHD Content-Type: message/rfc822 Received: from AMRXV1002.dir.svc.accenture.com ([10.10.160.62]) by mtahm1100.accenture.com (Lotus Domino Release 5.0.9a) with ESMTP id 2009020914165788:77437 ; Mon, 9 Feb 2009 14:16:57 -0600 Received: from AMRXB1002.dir.svc.accenture.com ([10.10.160.66]) by AMRXV1002.dir.svc.accenture.com with Microsoft SMTPSVC(6.0.3790.1830); Mon, 9 Feb 2009 14:16:12 -0600 Received: from amrmr1003.accenture.com ([170.252.248.72]) by AMRXB1002.dir.svc.accenture.com with Microsoft SMTPSVC(6.0.3790.1830); Mon, 9 Feb 2009 14:16:12 -0600 Received: from mail110-va3-R.bigfish.com (mail-va3.bigfish.com [216.32.180.113]) by amrmr1003.accenture.com (8.13.8/8.13.8) with ESMTP id n19KG9CS021120 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=FAIL) for ; Mon, 9 Feb 2009 14:16:11 -0600 (CST) Received: from mail110-va3 (localhost.localdomain [127.0.0.1]) by mail110-va3-R.bigfish.com (Postfix) with ESMTP id 4D8DE10008F for ; Mon, 9 Feb 2009 20:16:09 +0000 (UTC) Received: by mail110-va3 (MessageSwitch) id 123421056981910_11174; Mon, 9 Feb 2009 20:16:09 +0000 (UCT) Received: from Albanis-3.local (unknown [87.99.72.11]) by mail110-va3.bigfish.com (Postfix) with ESMTP id E3C59AD0061 for ; Mon, 9 Feb 2009 20:16:08 +0000 (UTC) Received: by Albanis-3.local (Postfix, from userid 501) id E1D7B328DAA; Mon, 9 Feb 2009 22:16:00 +0200 (EET) X-BigFish: vps9(zzzzzzz2dh6bh43j68o) X-Spam-TCS-SCL: 7:0 X-MS-Exchange-Organization-Antispam-Report: OrigIP: 87.99.72.11;Service: EHS Date: Mon, 9 Feb 2009 22:15:33 +0200 From: ameriks@amerimail.lv Reply-To: ginta.amerika@ameri.lv To: this_doesnotexistinAAc@accenture.com Subject: subjecting Mime-Version: 1.0 Message-Id: <20090209201600.E1D7B328DAA@Albanis-3.local> Return-Path: bounces-main+this_doesnotexistinAAc=accenture.com@amerimail.lv X-OriginalArrivalTime: 09 Feb 2009 20:16:12.0664 (UTC) FILETIME=[40DC5F80:01C98AF3] X-MIMETrack: Itemize by SMTP Server on MTAHM1100/Server/Accenture(Release 5.0.9a |January 7, 2002) at 02/09/2009 02:16:57 PM, Serialize by Router on MTAHM1100/Server/Accenture(Release 5.0.9a |January 7, 2002) at 02/09/2009 02:16:58 PM, Serialize complete at 02/09/2009 02:16:58 PM Content-Type: text/html; charset=utf-8 Hello from mars! --==IFJRGLKFGIR48542UHRUHIHD-- schleuder-3.6.0/spec/fixtures/mails/bounces/tt_1234211357.txt.eml000066400000000000000000000061551401002544500241460ustar00rootroot00000000000000From MAILER-DAEMON Mon Feb 9 22:29:17 2009 Return-Path: <> X-Original-To: bounces-main+agris.ameriksNEEXISTEE=gmail.com@amerimail.lv Delivered-To: bounce_and_mail_handler@ameriks Received: from Albanis-3.local (unknown [87.99.72.11]) by ameriks (Postfix) with ESMTP id 980243A08C for ; Mon, 9 Feb 2009 22:29:17 +0200 (EET) Received: by Albanis-3.local (Postfix) id 659FB328E84; Mon, 9 Feb 2009 22:29:16 +0200 (EET) Date: Mon, 9 Feb 2009 22:29:16 +0200 (EET) From: MAILER-DAEMON@Albanis-3.local (Mail Delivery System) Subject: Undelivered Mail Returned to Sender To: bounces-main+agris.ameriksNEEXISTEE=gmail.com@amerimail.lv Auto-Submitted: auto-replied MIME-Version: 1.0 Content-Type: multipart/report; report-type=delivery-status; boundary="51830328E80.1234211356/Albanis-3.local" Message-Id: <20090209202916.659FB328E84@Albanis-3.local> This is a MIME-encapsulated message. --51830328E80.1234211356/Albanis-3.local Content-Description: Notification Content-Type: text/plain; charset=us-ascii This is the mail system at host Albanis-3.local. I'm sorry to have to inform you that your message could not be delivered to one or more recipients. It's attached below. For further assistance, please send mail to postmaster. If you do so, please include this problem report. You can delete your own text from the attached returned message. The mail system : host gmail-smtp-in.l.google.com[209.85.218.64] said: 550-5.1.1 The email account that you tried to reach does not exist. Please 550-5.1.1 try double-checking the recipient's email address for typos 550-5.1.1 or unnecessary spaces. Learn more at 550 5.1.1 http://mail.google.com/support/bin/answer.py?answer=6596 20si2615223bwz.60 (in reply to RCPT TO command) --51830328E80.1234211356/Albanis-3.local Content-Description: Delivery report Content-Type: message/delivery-status Reporting-MTA: dns; Albanis-3.local X-Postfix-Queue-ID: 51830328E80 X-Postfix-Sender: rfc822; bounces-main@amerimail.lv Arrival-Date: Mon, 9 Feb 2009 22:29:11 +0200 (EET) Final-Recipient: rfc822; agris.ameriksNEEXISTEE@gmail.com Action: failed Status: 5.1.1 Remote-MTA: dns; gmail-smtp-in.l.google.com Diagnostic-Code: smtp; 550-5.1.1 The email account that you tried to reach does not exist. Please 550-5.1.1 try double-checking the recipient's email address for typos 550-5.1.1 or unnecessary spaces. Learn more at 550 5.1.1 http://mail.google.com/support/bin/answer.py?answer=6596 20si2615223bwz.60 --51830328E80.1234211356/Albanis-3.local Content-Description: Undelivered Message Content-Type: message/rfc822 Received: by Albanis-3.local (Postfix, from userid 501) id 51830328E80; Mon, 9 Feb 2009 22:29:11 +0200 (EET) Date: Mon, 9 Feb 2009 22:29:05 +0200 From: ameriks@amerimail.lv Reply-To: ginta.amerika@ameri.lv To: agris.ameriksNEEXISTEE@gmail.com Subject: subjecting Mime-Version: 1.0 Content-Type: text/html; charset=utf-8 Message-Id: <20090209202911.51830328E80@Albanis-3.local> Hello from mars! --51830328E80.1234211356/Albanis-3.local-- schleuder-3.6.0/spec/fixtures/mails/bounces/tt_1234211929.txt.eml000066400000000000000000000071331401002544500241500ustar00rootroot00000000000000From MAILER-DAEMON Mon Feb 9 22:38:49 2009 Return-Path: <> X-Original-To: bounces-main+jekaterina=tv5.lv@amerimail.lv Delivered-To: bounce_and_mail_handler@ameriks Received: from blackbird.grafton.lv (blackbird.grafton.lv [159.148.13.8]) by ameriks (Postfix) with ESMTP id C45293A08C for ; Mon, 9 Feb 2009 22:38:49 +0200 (EET) Received: by blackbird.grafton.lv (Postfix) id 89ACB620076; Mon, 9 Feb 2009 22:38:49 +0200 (EET) Date: Mon, 9 Feb 2009 22:38:49 +0200 (EET) From: MAILER-DAEMON@blackbird.grafton.lv (Mail Delivery System) Subject: Undelivered Mail Returned to Sender To: bounces-main+jekaterina=tv5.lv@amerimail.lv Auto-Submitted: auto-replied MIME-Version: 1.0 Content-Type: multipart/report; report-type=delivery-status; boundary="02136620074.1234211929/blackbird.grafton.lv" Message-Id: <20090209203849.89ACB620076@blackbird.grafton.lv> This is a MIME-encapsulated message. --02136620074.1234211929/blackbird.grafton.lv Content-Description: Notification Content-Type: text/plain; charset=us-ascii This is the mail system at host blackbird.grafton.lv. I'm sorry to have to inform you that your message could not be delivered to one or more recipients. It's attached below. For further assistance, please send mail to postmaster. If you do so, please include this problem report. You can delete your own text from the attached returned message. The mail system : maildir delivery failed: Sorry, the user's maildir has overdrawn his diskspace quota, please try again later. --02136620074.1234211929/blackbird.grafton.lv Content-Description: Delivery report Content-Type: message/delivery-status Reporting-MTA: dns; blackbird.grafton.lv X-Postfix-Queue-ID: 02136620074 X-Postfix-Sender: rfc822; bounces-main+jekaterina=tv5.lv@amerimail.lv Arrival-Date: Mon, 9 Feb 2009 22:38:48 +0200 (EET) Final-Recipient: rfc822; jekaterina@tv5.lv Original-Recipient: rfc822;jekaterina@tv5.lv Action: failed Status: 5.2.3 Diagnostic-Code: X-Postfix; maildir delivery failed: Sorry, the user's maildir has overdrawn his diskspace quota, please try again later. --02136620074.1234211929/blackbird.grafton.lv Content-Description: Undelivered Message Content-Type: message/rfc822 Received: from Albanis-3.local (unknown [87.99.72.11]) by blackbird.grafton.lv (Postfix) with ESMTP id C92D475C04F for ; Mon, 9 Feb 2009 22:38:48 +0200 (EET) Received: by Albanis-3.local (Postfix, from userid 501) id 900D9328EDE; Mon, 9 Feb 2009 22:38:47 +0200 (EET) Date: Mon, 9 Feb 2009 22:33:44 +0200 From: ameriks@amerimail.lv Reply-To: ginta.amerika@ameri.lv To: jekaterina@tv5.lv Subject: Mes loti atvainojamies, ja sanemat so epastu Mime-Version: 1.0 Content-Type: text/html; charset=utf-8 Message-Id: <20090209203848.900D9328EDE@Albanis-3.local> X-GRAFTON-MailScanner-Information: Scanned by GRAFTON mailscanner service X-GRAFTON-MailScanner-ID: C92D475C04F.83B56 X-GRAFTON-MailScanner: Found to be clean X-GRAFTON-MailScanner-SpamCheck: not spam, SpamAssassin (not cached, score=1.656, required 5, BAYES_50 0.00, HTML_MESSAGE 0.00, HTML_MIME_NO_HTML_TAG 0.10, MIME_HTML_ONLY 1.46, RDNS_NONE 0.10) X-GRAFTON-MailScanner-SpamScore: s X-GRAFTON-MailScanner-From: bounces-main+jekaterina=tv5.lv@amerimail.lv X-Spam-Status: No Labdien, mes loti atvainojamies, ja sanemat so epastu. Mes paslaik veicam jaunas sistemas izstradi, kur ir arii ieklauta epastu sutisana. Ludzu ignorejiet so e-pastu! Paldies par sapratni. Ja jus velaties ar mums sazinaties si epasta sakaraa, sutiet epastu uz agris.ameriks@ameri.lv. --02136620074.1234211929/blackbird.grafton.lv-- schleuder-3.6.0/spec/fixtures/mails/bounces/tt_1234211931.txt.eml000066400000000000000000000070471401002544500241450ustar00rootroot00000000000000From MAILER-DAEMON Mon Feb 9 22:38:51 2009 Return-Path: <> X-Original-To: bounces-main+info.rietumuradio.lv=mail.studio7.lv@amerimail.lv Delivered-To: bounce_and_mail_handler@ameriks Received: from mail.studio7pro.lv (mail.studio7pro.lv [159.148.225.2]) by ameriks (Postfix) with ESMTP id 177B73A08C for ; Mon, 9 Feb 2009 22:38:51 +0200 (EET) Received: by mail.studio7pro.lv (Postfix) id C3C2E108808A; Mon, 9 Feb 2009 22:38:50 +0200 (EET) Date: Mon, 9 Feb 2009 22:38:50 +0200 (EET) From: MAILER-DAEMON@mail.studio7pro.lv (Mail Delivery System) Subject: Undelivered Mail Returned to Sender To: bounces-main+info.rietumuradio.lv=mail.studio7.lv@amerimail.lv MIME-Version: 1.0 Content-Type: multipart/report; report-type=delivery-status; boundary="B3C4D108806F.1234211930/mail.studio7pro.lv" Content-Transfer-Encoding: 7bit Message-Id: <20090209203850.C3C2E108808A@mail.studio7pro.lv> This is a MIME-encapsulated message. --B3C4D108806F.1234211930/mail.studio7pro.lv Content-Description: Notification Content-Type: text/plain This is the Postfix program at host mail.studio7pro.lv. I'm sorry to have to inform you that your message could not be delivered to one or more recipients. It's attached below. For further assistance, please send mail to If you do so, please include this problem report. You can delete your own text from the attached returned message. The Postfix program : mail for mail.studio7.lv loops back to myself --B3C4D108806F.1234211930/mail.studio7pro.lv Content-Description: Delivery report Content-Type: message/delivery-status Reporting-MTA: dns; mail.studio7pro.lv X-Postfix-Queue-ID: B3C4D108806F X-Postfix-Sender: rfc822; bounces-main+info.rietumuradio.lv=mail.studio7.lv@amerimail.lv Arrival-Date: Mon, 9 Feb 2009 22:38:50 +0200 (EET) Final-Recipient: rfc822; info.rietumuradio.lv@mail.studio7.lv Action: failed Status: 5.0.0 Diagnostic-Code: X-Postfix; mail for mail.studio7.lv loops back to myself --B3C4D108806F.1234211930/mail.studio7pro.lv Content-Description: Undelivered Message Content-Type: message/rfc822 Content-Transfer-Encoding: 7bit Received: from localhost (SpamFilter [10.10.0.216]) by mail.studio7pro.lv (Postfix) with ESMTP id B3C4D108806F for ; Mon, 9 Feb 2009 22:38:50 +0200 (EET) X-Virus-Scanned: amavisd-new at studio7pro.lv Received: from mail.studio7pro.lv ([10.10.0.2]) by localhost (mx1.studio7pro.lv [10.10.0.216]) (amavisd-new, port 10024) with ESMTP id uIwSm-zP27+k for ; Mon, 9 Feb 2009 22:38:48 +0200 (EET) Received: from Albanis-3.local (unknown [87.99.72.11]) by mail.studio7pro.lv (Postfix) with ESMTP for ; Mon, 9 Feb 2009 22:38:48 +0200 (EET) Received: by Albanis-3.local (Postfix, from userid 501) id A0627328EE6; Mon, 9 Feb 2009 22:38:47 +0200 (EET) Date: Mon, 9 Feb 2009 22:38:23 +0200 From: ameriks@amerimail.lv Reply-To: ginta.amerika@ameri.lv To: info.rietumuradio.lv@mail.studio7.lv Subject: Mes loti atvainojamies, ja sanemat so epastu Mime-Version: 1.0 Content-Type: text/html; charset=utf-8 Message-Id: <20090209203848.A0627328EE6@Albanis-3.local> Labdien, mes loti atvainojamies, ja sanemat so epastu. Mes paslaik veicam jaunas sistemas izstradi, kur ir arii ieklauta epastu sutisana. Ludzu ignorejiet so e-pastu! Paldies par sapratni. Ja jus velaties ar mums sazinaties si epasta sakaraa, sutiet epastu uz agris.ameriks@ameri.lv. --B3C4D108806F.1234211930/mail.studio7pro.lv-- schleuder-3.6.0/spec/fixtures/mails/bounces/tt_1234211932.txt.eml000066400000000000000000000055501401002544500241430ustar00rootroot00000000000000From MAILER-DAEMON Mon Feb 9 22:38:52 2009 Return-Path: <> X-Original-To: bounces-main+dace.balode=rigasvilni.lv@amerimail.lv Delivered-To: bounce_and_mail_handler@ameriks Received: from Albanis-3.local (unknown [87.99.72.11]) by ameriks (Postfix) with ESMTP id 3A6443A08C for ; Mon, 9 Feb 2009 22:38:52 +0200 (EET) Received: by Albanis-3.local (Postfix) id 034F0328EF3; Mon, 9 Feb 2009 22:38:52 +0200 (EET) Date: Mon, 9 Feb 2009 22:38:52 +0200 (EET) From: MAILER-DAEMON@Albanis-3.local (Mail Delivery System) Subject: Undelivered Mail Returned to Sender To: bounces-main+dace.balode=rigasvilni.lv@amerimail.lv Auto-Submitted: auto-replied MIME-Version: 1.0 Content-Type: multipart/report; report-type=delivery-status; boundary="9764D328EE1.1234211932/Albanis-3.local" Message-Id: <20090209203852.034F0328EF3@Albanis-3.local> This is a MIME-encapsulated message. --9764D328EE1.1234211932/Albanis-3.local Content-Description: Notification Content-Type: text/plain; charset=us-ascii This is the mail system at host Albanis-3.local. I'm sorry to have to inform you that your message could not be delivered to one or more recipients. It's attached below. For further assistance, please send mail to postmaster. If you do so, please include this problem report. You can delete your own text from the attached returned message. The mail system : host mail.rigasvilni.lv[159.148.4.100] said: 550 sorry, no mailbox here by that name. (#5.7.17) (in reply to RCPT TO command) --9764D328EE1.1234211932/Albanis-3.local Content-Description: Delivery report Content-Type: message/delivery-status Reporting-MTA: dns; Albanis-3.local X-Postfix-Queue-ID: 9764D328EE1 X-Postfix-Sender: rfc822; bounces-main@amerimail.lv Arrival-Date: Mon, 9 Feb 2009 22:38:47 +0200 (EET) Final-Recipient: rfc822; dace.balode@rigasvilni.lv Action: failed Status: 5.0.0 Remote-MTA: dns; mail.rigasvilni.lv Diagnostic-Code: smtp; 550 sorry, no mailbox here by that name. (#5.7.17) --9764D328EE1.1234211932/Albanis-3.local Content-Description: Undelivered Message Content-Type: message/rfc822 Received: by Albanis-3.local (Postfix, from userid 501) id 9764D328EE1; Mon, 9 Feb 2009 22:38:47 +0200 (EET) Date: Mon, 9 Feb 2009 22:36:06 +0200 From: ameriks@amerimail.lv Reply-To: ginta.amerika@ameri.lv To: dace.balode@rigasvilni.lv Subject: Mes loti atvainojamies, ja sanemat so epastu Mime-Version: 1.0 Content-Type: text/html; charset=utf-8 Message-Id: <20090209203848.9764D328EE1@Albanis-3.local> Labdien, mes loti atvainojamies, ja sanemat so epastu. Mes paslaik veicam jaunas sistemas izstradi, kur ir arii ieklauta epastu sutisana. Ludzu ignorejiet so e-pastu! Paldies par sapratni. Ja jus velaties ar mums sazinaties si epasta sakaraa, sutiet epastu uz agris.ameriks@ameri.lv. --9764D328EE1.1234211932/Albanis-3.local-- schleuder-3.6.0/spec/fixtures/mails/bounces/tt_1234241665.txt.eml000066400000000000000000000055271401002544500241550ustar00rootroot00000000000000From MAILER-DAEMON Tue Feb 10 06:54:25 2009 Return-Path: <> X-Original-To: bounces-main+annas=sfl.lv@amerimail.lv Delivered-To: bounce_and_mail_handler@ameriks Received: from Albanis-3.local (unknown [87.99.72.11]) by ameriks (Postfix) with ESMTP id 4B5B13A08C for ; Tue, 10 Feb 2009 06:54:25 +0200 (EET) Received: by Albanis-3.local (Postfix) id 022EF32925F; Tue, 10 Feb 2009 06:54:25 +0200 (EET) Date: Tue, 10 Feb 2009 06:54:25 +0200 (EET) From: MAILER-DAEMON@Albanis-3.local (Mail Delivery System) Subject: Undelivered Mail Returned to Sender To: bounces-main+annas=sfl.lv@amerimail.lv Auto-Submitted: auto-replied MIME-Version: 1.0 Content-Type: multipart/report; report-type=delivery-status; boundary="9406E328EE0.1234241665/Albanis-3.local" Message-Id: <20090210045425.022EF32925F@Albanis-3.local> This is a MIME-encapsulated message. --9406E328EE0.1234241665/Albanis-3.local Content-Description: Notification Content-Type: text/plain; charset=us-ascii This is the mail system at host Albanis-3.local. I'm sorry to have to inform you that your message could not be delivered to one or more recipients. It's attached below. For further assistance, please send mail to postmaster. If you do so, please include this problem report. You can delete your own text from the attached returned message. The mail system : host mx.latnet.lv[92.240.64.15] said: 550 : Recipient address rejected: User unknown in virtual mailbox table (in reply to RCPT TO command) --9406E328EE0.1234241665/Albanis-3.local Content-Description: Delivery report Content-Type: message/delivery-status Reporting-MTA: dns; Albanis-3.local X-Postfix-Queue-ID: 9406E328EE0 X-Postfix-Sender: rfc822; bounces-main@amerimail.lv Arrival-Date: Mon, 9 Feb 2009 22:38:47 +0200 (EET) Final-Recipient: rfc822; annas@sfl.lv Action: failed Status: 5.0.0 Remote-MTA: dns; mx.latnet.lv Diagnostic-Code: smtp; 550 : Recipient address rejected: User unknown in virtual mailbox table --9406E328EE0.1234241665/Albanis-3.local Content-Description: Undelivered Message Content-Type: message/rfc822 Received: by Albanis-3.local (Postfix, from userid 501) id 9406E328EE0; Mon, 9 Feb 2009 22:38:47 +0200 (EET) Date: Mon, 9 Feb 2009 22:35:24 +0200 From: ameriks@amerimail.lv Reply-To: ginta.amerika@ameri.lv To: annas@sfl.lv Subject: Mes loti atvainojamies, ja sanemat so epastu Mime-Version: 1.0 Content-Type: text/html; charset=utf-8 Message-Id: <20090209203848.9406E328EE0@Albanis-3.local> Labdien, mes loti atvainojamies, ja sanemat so epastu. Mes paslaik veicam jaunas sistemas izstradi, kur ir arii ieklauta epastu sutisana. Ludzu ignorejiet so e-pastu! Paldies par sapratni. Ja jus velaties ar mums sazinaties si epasta sakaraa, sutiet epastu uz agris.ameriks@ameri.lv. --9406E328EE0.1234241665/Albanis-3.local-- schleuder-3.6.0/spec/fixtures/mails/bounces/tt_1234285532.txt.eml000066400000000000000000000060771401002544500241570ustar00rootroot00000000000000From MAILER-DAEMON Tue Feb 10 19:05:32 2009 Return-Path: <> X-Original-To: bounces-main+doesntexistthisemaill=yahoo.com@amerimail.lv Delivered-To: bounce_and_mail_handler@ameriks Received: from Albanis-3.local (unknown [87.99.72.11]) by ameriks (Postfix) with ESMTP id 5AFF43A08C for ; Tue, 10 Feb 2009 19:05:32 +0200 (EET) Received: by Albanis-3.local (Postfix) id E6CFF329D08; Tue, 10 Feb 2009 19:05:31 +0200 (EET) Date: Tue, 10 Feb 2009 19:05:31 +0200 (EET) From: MAILER-DAEMON@Albanis-3.local (Mail Delivery System) Subject: Undelivered Mail Returned to Sender To: bounces-main+doesntexistthisemaill=yahoo.com@amerimail.lv Auto-Submitted: auto-replied MIME-Version: 1.0 Content-Type: multipart/report; report-type=delivery-status; boundary="50514329496.1234285531/Albanis-3.local" Message-Id: <20090210170531.E6CFF329D08@Albanis-3.local> This is a MIME-encapsulated message. --50514329496.1234285531/Albanis-3.local Content-Description: Notification Content-Type: text/plain; charset=us-ascii This is the mail system at host Albanis-3.local. I'm sorry to have to inform you that your message could not be delivered to one or more recipients. It's attached below. For further assistance, please send mail to postmaster. If you do so, please include this problem report. You can delete your own text from the attached returned message. The mail system : host d.mx.mail.yahoo.com[66.196.82.7] said: 554 delivery error: dd This user doesn't have a yahoo.com account (doesntexistthisemaill@yahoo.com) [0] - mta153.mail.re1.yahoo.com (in reply to end of DATA command) --50514329496.1234285531/Albanis-3.local Content-Description: Delivery report Content-Type: message/delivery-status Reporting-MTA: dns; Albanis-3.local X-Postfix-Queue-ID: 50514329496 X-Postfix-Sender: rfc822; bounces-main@amerimail.lv Arrival-Date: Tue, 10 Feb 2009 18:56:27 +0200 (EET) Final-Recipient: rfc822; doesntexistthisemaill@yahoo.com Action: failed Status: 5.0.0 Remote-MTA: dns; d.mx.mail.yahoo.com Diagnostic-Code: smtp; 554 delivery error: dd This user doesn't have a yahoo.com account (doesntexistthisemaill@yahoo.com) [0] - mta153.mail.re1.yahoo.com --50514329496.1234285531/Albanis-3.local Content-Description: Undelivered Message Content-Type: message/rfc822 Received: by Albanis-3.local (Postfix, from userid 501) id 50514329496; Tue, 10 Feb 2009 18:56:27 +0200 (EET) Date: Tue, 10 Feb 2009 18:53:50 +0200 From: ameriks@amerimail.lv Reply-To: ginta.amerika@ameri.lv To: doesntexistthisemaill@yahoo.com Subject: Mes loti atvainojamies, ja sanemat so epastu Mime-Version: 1.0 Content-Type: text/html; charset=utf-8 Message-Id: <20090210165627.50514329496@Albanis-3.local> Labdien, mes loti atvainojamies, ja sanemat so epastu. Mes paslaik veicam jaunas sistemas izstradi, kur ir arii ieklauta epastu sutisana. Ludzu ignorejiet so e-pastu! Paldies par sapratni. Ja jus velaties ar mums sazinaties si epasta sakaraa, sutiet epastu uz agris.ameriks@ameri.lv. --50514329496.1234285531/Albanis-3.local-- schleuder-3.6.0/spec/fixtures/mails/bounces/tt_1234285668.txt.eml000066400000000000000000000054511401002544500241640ustar00rootroot00000000000000From MAILER-DAEMON Tue Feb 10 19:07:48 2009 Return-Path: <> X-Original-To: bounces-main+agrisa=one.lv@amerimail.lv Delivered-To: bounce_and_mail_handler@ameriks Received: from Albanis-3.local (unknown [87.99.72.11]) by ameriks (Postfix) with ESMTP id EE9CC3A1A4 for ; Tue, 10 Feb 2009 19:07:47 +0200 (EET) Received: by Albanis-3.local (Postfix) id 89FF3329E3C; Tue, 10 Feb 2009 19:07:47 +0200 (EET) Date: Tue, 10 Feb 2009 19:07:47 +0200 (EET) From: MAILER-DAEMON@Albanis-3.local (Mail Delivery System) Subject: Undelivered Mail Returned to Sender To: bounces-main+agrisa=one.lv@amerimail.lv Auto-Submitted: auto-replied MIME-Version: 1.0 Content-Type: multipart/report; report-type=delivery-status; boundary="7895C329E32.1234285667/Albanis-3.local" Message-Id: <20090210170747.89FF3329E3C@Albanis-3.local> This is a MIME-encapsulated message. --7895C329E32.1234285667/Albanis-3.local Content-Description: Notification Content-Type: text/plain; charset=us-ascii This is the mail system at host Albanis-3.local. I'm sorry to have to inform you that your message could not be delivered to one or more recipients. It's attached below. For further assistance, please send mail to postmaster. If you do so, please include this problem report. You can delete your own text from the attached returned message. The mail system : host mail5.one.lv[62.85.54.62] said: 552 Account(s) does not have enough space (in reply to end of DATA command) --7895C329E32.1234285667/Albanis-3.local Content-Description: Delivery report Content-Type: message/delivery-status Reporting-MTA: dns; Albanis-3.local X-Postfix-Queue-ID: 7895C329E32 X-Postfix-Sender: rfc822; bounces-main@amerimail.lv Arrival-Date: Tue, 10 Feb 2009 19:07:47 +0200 (EET) Final-Recipient: rfc822; agrisa@one.lv Action: failed Status: 5.0.0 Remote-MTA: dns; mail5.one.lv Diagnostic-Code: smtp; 552 Account(s) does not have enough space --7895C329E32.1234285667/Albanis-3.local Content-Description: Undelivered Message Content-Type: message/rfc822 Received: by Albanis-3.local (Postfix, from userid 501) id 7895C329E32; Tue, 10 Feb 2009 19:07:47 +0200 (EET) Date: Tue, 10 Feb 2009 19:07:09 +0200 From: ameriks@amerimail.lv Reply-To: ginta.amerika@ameri.lv To: agrisa@one.lv Subject: Mes loti atvainojamies, ja sanemat so epastu Mime-Version: 1.0 Content-Type: text/html; charset=utf-8 Message-Id: <20090210170747.7895C329E32@Albanis-3.local> Labdien, mes loti atvainojamies, ja sanemat so epastu. Mes paslaik veicam jaunas sistemas izstradi, kur ir arii ieklauta epastu sutisana. Ludzu ignorejiet so e-pastu! Paldies par sapratni. Ja jus velaties ar mums sazinaties si epasta sakaraa, sutiet epastu uz agris.ameriks@ameri.lv. --7895C329E32.1234285667/Albanis-3.local-- schleuder-3.6.0/spec/fixtures/mails/bounces/tt_bounce_01.txt.eml000066400000000000000000000044461401002544500246460ustar00rootroot00000000000000Return-path: Received: from abcycf1m.cf.ac.uk ([131.251.4.14]) by crane2.cf.ac.uk with esmtp (Exim 3.03 #1) id 14KSwL-0002Fo-00 for thornborrow@connect4free.net; Sun, 21 Jan 2001 22:26:25 +0000 Received: from ABCYCF1M/SpoolDir by ABCYCF1M.CF.AC.UK (Mercury 1.48); 21 Jan 01 22:27:45 GMT0BST Received: from SpoolDir by ABCYCF1M (Mercury 1.48); 21 Jan 01 22:27:36 GMT0BST Received: from ABCYCF1M/SpoolDir by ABCYCF1M.CF.AC.UK (Mercury 1.48) for ; 21 Jan 01 22:27:35 GMT0BST Resent-from: SENJT3.STF.ENCAP.HUMS.CF@ABCYCF1M.CF.AC.UK Resent-to: thornborrow@connect4free.net Resent-Date: Sun, 21 Jan 2001 22:27:35 GMT0BST X-Autoforward: 1 Received: from pigeon.cf.ac.uk (131.251.0.2) by ABCYCF1M.CF.AC.UK (Mercury 1.48) with ESMTP; 21 Jan 01 22:27:25 GMT0BST Received: from sprog.auc.dk ([130.225.58.12] ident=majordom) by pigeon.cf.ac.uk with esmtp (Exim 3.03 #1) id 14KSw1-00079N-00 for ThornborrowJ1@Cardiff.ac.uk; Sun, 21 Jan 2001 22:26:05 +0000 Received: (from majordom@localhost) by sprog.auc.dk (8.9.1a/8.9.1) id VAA05111 for languse-outgoing; Sun, 21 Jan 2001 21:53:40 +0100 (MET) X-Authentication-Warning: sprog.auc.dk: majordom set sender to owner-languse@sprog.auc.dk using -f Received: from crane2.cf.ac.uk (crane2.cf.ac.uk [131.251.0.25]) by sprog.auc.dk (8.9.1a/8.9.1) with ESMTP id VAA05107 for ; Sun, 21 Jan 2001 21:53:39 +0100 (MET) Received: from exim by crane2.cf.ac.uk with local (Exim 3.03 #1) id 14KRU7-000239-00 for languse@sprog.auc.dk; Sun, 21 Jan 2001 20:53:11 +0000 X-Failed-Recipients: thornborrow@connect4free.net From: Mail Delivery System To: languse@sprog.auc.dk Subject: [languse] Mail delivery failed: returning message to sender Message-Id: Date: Sun, 21 Jan 2001 20:53:11 +0000 Sender: owner-languse@sprog.auc.dk Precedence: bulk Reply-To: languse@sprog.auc.dk, Mail Delivery System Resent-Message-Id: This message was created automatically by mail delivery software. A message that you sent could not be delivered to all of its recipients. The following address(es) failed: thornborrow@connect4free.net: unrouteable mail domain "connect4free.net" schleuder-3.6.0/spec/fixtures/mails/bounces/tt_bounce_02.txt.eml000066400000000000000000000044461401002544500246470ustar00rootroot00000000000000Return-path: Received: from abcycf1m.cf.ac.uk ([131.251.4.14]) by crane2.cf.ac.uk with esmtp (Exim 3.03 #1) id 14KRU7-000237-00 for thornborrow@connect4free.net; Sun, 21 Jan 2001 20:53:11 +0000 Received: from ABCYCF1M/SpoolDir by ABCYCF1M.CF.AC.UK (Mercury 1.48); 21 Jan 01 20:54:31 GMT0BST Received: from SpoolDir by ABCYCF1M (Mercury 1.48); 21 Jan 01 20:54:06 GMT0BST Received: from ABCYCF1M/SpoolDir by ABCYCF1M.CF.AC.UK (Mercury 1.48) for ; 21 Jan 01 20:54:04 GMT0BST Resent-from: SENJT3.STF.ENCAP.HUMS.CF@ABCYCF1M.CF.AC.UK Resent-to: thornborrow@connect4free.net Resent-Date: Sun, 21 Jan 2001 20:54:04 GMT0BST X-Autoforward: 1 Received: from pigeon.cf.ac.uk (131.251.0.2) by ABCYCF1M.CF.AC.UK (Mercury 1.48) with ESMTP; 21 Jan 01 20:53:58 GMT0BST Received: from sprog.auc.dk ([130.225.58.12] ident=majordom) by pigeon.cf.ac.uk with esmtp (Exim 3.03 #1) id 14KRTZ-0006gv-00 for ThornborrowJ1@Cardiff.ac.uk; Sun, 21 Jan 2001 20:52:38 +0000 Received: (from majordom@localhost) by sprog.auc.dk (8.9.1a/8.9.1) id UAA04001 for languse-outgoing; Sun, 21 Jan 2001 20:20:58 +0100 (MET) X-Authentication-Warning: sprog.auc.dk: majordom set sender to owner-languse@sprog.auc.dk using -f Received: from crane2.cf.ac.uk (crane2.cf.ac.uk [131.251.0.25]) by sprog.auc.dk (8.9.1a/8.9.1) with ESMTP id UAA03997 for ; Sun, 21 Jan 2001 20:20:56 +0100 (MET) Received: from exim by crane2.cf.ac.uk with local (Exim 3.03 #1) id 14KQ2O-0001rj-00 for languse@sprog.auc.dk; Sun, 21 Jan 2001 19:20:28 +0000 X-Failed-Recipients: thornborrow@connect4free.net From: Mail Delivery System To: languse@sprog.auc.dk Subject: [languse] Mail delivery failed: returning message to sender Message-Id: Date: Sun, 21 Jan 2001 19:20:28 +0000 Sender: owner-languse@sprog.auc.dk Precedence: bulk Reply-To: languse@sprog.auc.dk, Mail Delivery System Resent-Message-Id: This message was created automatically by mail delivery software. A message that you sent could not be delivered to all of its recipients. The following address(es) failed: thornborrow@connect4free.net: unrouteable mail domain "connect4free.net" schleuder-3.6.0/spec/fixtures/mails/bounces/tt_bounce_03.txt.eml000066400000000000000000000064741401002544500246530ustar00rootroot00000000000000Delivered-To: agris.ameriks@gmail.com Received: by 10.36.252.76 with SMTP id z76cs42358nzh; Mon, 28 Nov 2005 11:05:40 -0800 (PST) Received: by 10.36.251.8 with SMTP id y8mr3758555nzh; Mon, 28 Nov 2005 11:05:40 -0800 (PST) X-Forwarded-To: Agris.Ameriks@gmail.com X-Forwarded-For: ameriks@gmail.com Agris.Ameriks@gmail.com X-Gmail-Received: 499bf0339a8d4dd35bcd03d4596db02d01fdefc5 Delivered-To: ameriks@gmail.com Received: by 10.36.251.57 with SMTP id y57cs33742nzh; Mon, 28 Nov 2005 11:05:39 -0800 (PST) Received: by 10.48.3.5 with SMTP id 5mr493496nfc; Mon, 28 Nov 2005 11:05:39 -0800 (PST) Return-Path: <> Received: from apollo.lv (jupiter.apollo.lv [80.232.168.212]) by mx.gmail.com with ESMTP id o45si619017nfa.2005.11.28.11.05.09; Mon, 28 Nov 2005 11:05:39 -0800 (PST) Received-SPF: pass (gmail.com: best guess record for domain of apollo.lv designates 80.232.168.212 as permitted sender) Subject: Undeliverable mail: From: MAILER-DAEMON@apollo.lv To: Date: Mon, 28 Nov 2005 20:26:38 +0200 Message-ID: MIME-Version: 1.0 Content-Type: multipart/report; report-type="delivery-status"; boundary="_===110354846====apollo.lv===_" --_===110354846====apollo.lv===_ Content-Type: text/plain; charset="utf-8" Failed to deliver to '' Messages without To: fields are not accepted here --_===110354846====apollo.lv===_ Content-Type: message/delivery-status Reporting-MTA: dns; apollo.lv Original-Recipient: rfc822; Final-Recipient: system;<> Action: failed Status: 5.0.0 --_===110354846====apollo.lv===_ Content-Type: message/rfc822 Received: from zproxy.gmail.com ([64.233.162.194] verified) by apollo.lv (CommuniGate Pro SMTP 4.1.8) with ESMTP id 110354858 for agrisa@apollo.lv; Mon, 28 Nov 2005 20:26:37 +0200 Received: by zproxy.gmail.com with SMTP id s18so2823588nze for ; Mon, 28 Nov 2005 10:26:35 -0800 (PST) DomainKey-Signature: a=rsa-sha1; q=dns; c=nofws; s=beta; d=gmail.com; h=received:message-id:date:from:reply-to:subject:mime-version:content-type; b=tVddE1twi6/ew8gg2erlzR1AV4UgqT1v2d7+lazGsJr8a68QzxZLAhp/6NvW18kcpgqxRajkHztCLu0HYtQ+eR7iZLfM45EB6McOaZm0cfoySOIUl60KDFAH1LyW3Vl8lC7BNMCZwxomqaLI8kK2J8L/wOP/iqpdo0lFvDGFnsY= Received: by 10.37.15.37 with SMTP id s37mr3728494nzi; Mon, 28 Nov 2005 10:26:35 -0800 (PST) Received: by 10.36.251.57 with HTTP; Mon, 28 Nov 2005 10:26:35 -0800 (PST) Message-ID: <4abe0f090511281026t1436fa8dg844ce3c26184a927@mail.gmail.com> Date: Mon, 28 Nov 2005 20:26:35 +0200 From: Agris Ameriks Reply-To: Agris.Ameriks@gmail.com Subject: MIME-Version: 1.0 Content-Type: multipart/alternative; boundary="----=_Part_12151_7196822.1133202395822" ------=_Part_12151_7196822.1133202395822 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable Content-Disposition: inline lalallalalaasd -- Ar cienu, Agris Ameriks RSD Kulturas komitejas vaditajs ------=_Part_12151_7196822.1133202395822 Content-Type: text/html; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable Content-Disposition: inline lalallalalaasd

--
Ar cienu,
Agris Ameriks
RS= D Kulturas komitejas vaditajs ------=_Part_12151_7196822.1133202395822-- --_===110354846====apollo.lv===_-- schleuder-3.6.0/spec/fixtures/mails/bounces/tt_bounce_04.txt.eml000066400000000000000000000066541401002544500246540ustar00rootroot00000000000000Delivered-To: agris.ameriks@gmail.com Received: by 10.36.252.76 with SMTP id z76cs42363nzh; Mon, 28 Nov 2005 11:06:11 -0800 (PST) Received: by 10.36.25.8 with SMTP id 8mr3761324nzy; Mon, 28 Nov 2005 11:06:11 -0800 (PST) X-Forwarded-To: Agris.Ameriks@gmail.com X-Forwarded-For: ameriks@gmail.com Agris.Ameriks@gmail.com X-Gmail-Received: 2a7289d18d2f59a47dde79a70a1f4f6a690bcf51 Delivered-To: ameriks@gmail.com Received: by 10.36.251.57 with SMTP id y57cs33747nzh; Mon, 28 Nov 2005 11:06:11 -0800 (PST) Received: by 10.48.142.6 with SMTP id p6mr493395nfd; Mon, 28 Nov 2005 11:06:10 -0800 (PST) Return-Path: <> Received: from apollo.lv (jupiter.apollo.lv [80.232.168.212]) by mx.gmail.com with ESMTP id o45si619017nfa.2005.11.28.11.05.40; Mon, 28 Nov 2005 11:06:10 -0800 (PST) Received-SPF: pass (gmail.com: best guess record for domain of apollo.lv designates 80.232.168.212 as permitted sender) Subject: Undeliverable mail: asd From: MAILER-DAEMON@apollo.lv To: Date: Mon, 28 Nov 2005 20:27:07 +0200 Message-ID: MIME-Version: 1.0 Content-Type: multipart/report; report-type="delivery-status"; boundary="_===110354911====apollo.lv===_" --_===110354911====apollo.lv===_ Content-Type: text/plain; charset="utf-8" Failed to deliver to '' Messages without To: fields are not accepted here --_===110354911====apollo.lv===_ Content-Type: message/delivery-status Reporting-MTA: dns; apollo.lv Original-Recipient: rfc822; Final-Recipient: system;<> Action: failed Status: 5.0.0 --_===110354911====apollo.lv===_ Content-Type: message/rfc822 Received: from zproxy.gmail.com ([64.233.162.194] verified) by apollo.lv (CommuniGate Pro SMTP 4.1.8) with ESMTP id 110354880 for agrisa@apollo.lv; Mon, 28 Nov 2005 20:27:07 +0200 Received: by zproxy.gmail.com with SMTP id s18so2823588nze for ; Mon, 28 Nov 2005 10:27:06 -0800 (PST) DomainKey-Signature: a=rsa-sha1; q=dns; c=nofws; s=beta; d=gmail.com; h=received:message-id:date:from:reply-to:subject:cc:mime-version:content-type; b=lj7BO/1r1H6jaGsjuCV7+4IlSZdoBt1PCSkVXBc0Uh97j+EWpsbfAYPSbbqo6AzxkkCSaVLMXG5cszvroWXvUsKD1tVB0IY7DRP2mP6VEb0C60tHRRwPJkAGbaqq1Q9T8ih1OQGKdNdBxxod7gH5XhK2uXZZiAkaCbLBNPmU5es= Received: by 10.36.250.46 with SMTP id x46mr3723067nzh; Mon, 28 Nov 2005 10:27:06 -0800 (PST) Received: by 10.36.251.57 with HTTP; Mon, 28 Nov 2005 10:27:06 -0800 (PST) Message-ID: <4abe0f090511281027i654be30bt5c2405dc847bcbc4@mail.gmail.com> Date: Mon, 28 Nov 2005 20:27:06 +0200 From: Agris Ameriks Reply-To: Agris.Ameriks@gmail.com Subject: asd Cc: Agris Ameriks 2 , Agris Ameriks , ameriks@gmail.com MIME-Version: 1.0 Content-Type: multipart/alternative; boundary="----=_Part_12159_32010714.1133202426241" ------=_Part_12159_32010714.1133202426241 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable Content-Disposition: inline alalallalala -- Ar cienu, Agris Ameriks RSD Kulturas komitejas vaditajs ------=_Part_12159_32010714.1133202426241 Content-Type: text/html; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable Content-Disposition: inline alalallalala

--
Ar cienu,
Agris Ameriks
RSD = Kulturas komitejas vaditajs ------=_Part_12159_32010714.1133202426241-- --_===110354911====apollo.lv===_-- schleuder-3.6.0/spec/fixtures/mails/bounces/tt_bounce_05.txt.eml000066400000000000000000000070161401002544500246460ustar00rootroot00000000000000Delivered-To: agris.ameriks@gmail.com Received: by 10.100.94.18 with SMTP id r18cs649481anb; Tue, 8 May 2007 09:35:28 -0700 (PDT) Received: by 10.78.145.5 with SMTP id s5mr377920hud.1178642127951; Tue, 08 May 2007 09:35:27 -0700 (PDT) Return-Path: <> Received: from smtp2.apollo.lv (smtp2.apollo.lv [80.232.168.229]) by mx.google.com with ESMTP id 55si1194537ugq.2007.05.08.09.35.27; Tue, 08 May 2007 09:35:27 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of smtp2.apollo.lv designates 80.232.168.229 as permitted sender) X-Cloudmark-Score: 0.000000 [] X-Virusscan: Clamd Subject: Undeliverable mail: Labdien! From: To: Date: Tue, 08 May 2007 19:35:27 +0300 Message-ID: X-MAPI-Message-Class: REPORT.IPM.Note.NDR MIME-Version: 1.0 Content-Type: multipart/report; report-type="delivery-status"; boundary="_===92533048====smtp2.apollo.lv===_" --_===92533048====smtp2.apollo.lv===_ Content-Type: text/plain; charset="utf-8" Failed to deliver to 'evor@apollo.lv' SMTP module(domain pop.apollo.lv) reports: host pop.apollo.lv says: 550 evor@apollo.lv unknown user account --_===92533048====smtp2.apollo.lv===_ Content-Type: message/delivery-status Reporting-MTA: dns; smtp2.apollo.lv Original-Recipient: rfc822; Final-Recipient: rfc822; Action: failed Status: 5.0.0 --_===92533048====smtp2.apollo.lv===_ Content-Type: message/rfc822 Received: from wr-out-0506.google.com ([64.233.184.231] verified) by smtp2.apollo.lv (CommuniGate Pro SMTP 5.0.10) with ESMTP id 92533044 for evor@apollo.lv; Tue, 08 May 2007 19:35:26 +0300 Received: by wr-out-0506.google.com with SMTP id 25so1879201wry for ; Tue, 08 May 2007 09:35:20 -0700 (PDT) DKIM-Signature: a=rsa-sha1; c=relaxed/relaxed; d=gmail.com; s=beta; h=domainkey-signature:received:received:message-id:date:from:to:subject:mime-version:content-type:content-transfer-encoding:content-disposition; b=Sa8LZ3AQtQcbyYJx8yrTBpc8FMFhKCE7Hm1Vm4QSvn+teR7CpqPcEGUSWSNklzqPAzN+VsnFUgBwnxcRNi0+YddsnmgZWmI9V6HaUniXHxvAlId36z4UjTKSrGXb3dv/xwcTRut8AFmKdACrnxpiRPp+R1uqHbR2pMFotkynuCs= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=beta; h=received:message-id:date:from:to:subject:mime-version:content-type:content-transfer-encoding:content-disposition; b=giHBorElbW7SdOhu+wcknrVopvrUVV9io1n7dG3HI0+bZfYRYh1MAb2fAMbWGCvG13UjU1TZHds84xZ0xvKDGcKVIhCXb7mfo3XZCQoPyup7IHrcr/TPlLEf1MpKw1oCmk5NS1u5nVVYf2FZsI4kGZvoGeJHP68orx5PmlIEQXQ= Received: by 10.100.230.13 with SMTP id c13mr3322842anh.1178642116550; Tue, 08 May 2007 09:35:16 -0700 (PDT) Received: by 10.100.94.18 with HTTP; Tue, 8 May 2007 09:35:16 -0700 (PDT) Message-ID: Date: Tue, 8 May 2007 19:35:16 +0300 From: "Agris Ameriks" To: evor@apollo.lv Subject: Labdien! MIME-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-13; format=flowed Content-Transfer-Encoding: base64 Content-Disposition: inline TGFiZGllbiEKCkVzIGludGVyZXPnam9zLCBjaWsgdmFy53R1IGl6bWFrc+J0IDE1LnNlcHRlbWJy 7iBub2Ryb/BpbuJ0IGvicnTuYnUKVudybWFuZXMgZOJyeuIgbm8gMTQ6MDAgLSAyMzowMC4gKHBh c+JrdW1zIG5vcml053Mgbm8gMTU6MDAgLSAyMjoyMCkuCgpNYW4gaW50ZXJlc+csIGNpayBpem1h a3PidHU6CjEpIDYgYXBzYXJnaS4KMikgMTAgYXBzYXJnaS4KCi0tIApBciBjaWXydSwKQWdyaXMg QW1lcmlrcwpNb2IudGVsLiAyIDY0NjExMDEKRS1wYXN0czogQWdyaXMuQW1lcmlrc0BnbWFpbC5j b20K --_===92533048====smtp2.apollo.lv===_-- schleuder-3.6.0/spec/fixtures/mails/bounces/tt_bounce_06.txt.eml000066400000000000000000000040701401002544500246440ustar00rootroot00000000000000Delivered-To: agris.ameriks@gmail.com Received: by 10.100.94.18 with SMTP id r18cs650238anb; Tue, 8 May 2007 09:44:00 -0700 (PDT) Received: by 10.100.240.19 with SMTP id n19mr5850181anh.1178642640024; Tue, 08 May 2007 09:44:00 -0700 (PDT) Return-Path: <> Received: by 10.100.240.19 with SMTP id n19mr8655080anh; Tue, 08 May 2007 09:44:00 -0700 (PDT) Message-ID: <16368e24c8042ff81fe0345a2d1c5@googlemail.com> From: Mail Delivery Subsystem To: agris.ameriks@gmail.com Subject: Delivery Status Notification (Failure) Date: Tue, 08 May 2007 09:44:00 -0700 (PDT) This is an automatically generated Delivery Status Notification Delivery to the following recipient failed permanently: info@koblenz.lv Technical details of permanent failure: PERM_FAILURE: SMTP Error (state 9): 550 5.7.1 Your message (sent through 209.85.132.244) was blocked by ROTA DNSBL. If you are not a spammer, open http://www.rota.lv/DNSBL and follow instructions or call +371 7019029, or send an e-mail message from another address to dz@ROTA.lv with the blocked sender e-mail name. ----- Original message ----- Received: by 10.100.240.19 with SMTP id n19mr5850084anh.1178642634965; Tue, 08 May 2007 09:43:54 -0700 (PDT) Received: by 10.100.94.18 with HTTP; Tue, 8 May 2007 09:43:54 -0700 (PDT) Message-ID: Date: Tue, 8 May 2007 19:43:54 +0300 From: "Agris Ameriks" To: agrisa@apollo.lv Subject: Labdien! MIME-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-13; format=flowed Content-Transfer-Encoding: base64 Content-Disposition: inline TGFiZGllbiEKCkVzIGludGVyZXPnam9zLCBjaWsgdmFy53R1IGl6bWFrc+J0IDE1LnNlcHRlbWJy 7iBub2Ryb/BpbuJ0IGvicnTuYnUKVudybWFuZXMgZOJyeuIgbm8gMTQ6MDAgLSAyMzowMC4gKHBh c+JrdW1zIG5vcml053Mgbm8gMTU6MDAgLSAyMjoyMCkuCgpNYW4gaW50ZXJlc+csIGNpayBpem1h a3PidHU6CjEpIDYgYXBzYXJnaS4KMikgMTAgYXBzYXJnaS4KCi0tIApBciBjaWXydSwKQWdyaXMg QW1lcmlrcwpNb2IudGVsLiAyIDY0NjExMDEKRS1wYXN0czogQWdyaXMuQW1lcmlrc0BnbWFpbC5j b20K ----- End of message ----- schleuder-3.6.0/spec/fixtures/mails/bounces/tt_bounce_07.txt.eml000066400000000000000000000103051401002544500246430ustar00rootroot00000000000000Delivered-To: agris.ameriks@gmail.com Received: by 10.66.225.19 with SMTP id x19cs81231ugg; Mon, 4 Jun 2007 15:20:37 -0700 (PDT) Received: by 10.67.89.6 with SMTP id r6mr7631ugl.1180995637243; Mon, 04 Jun 2007 15:20:37 -0700 (PDT) Return-Path: <> Received: from avalon.telekom.lv ([194.8.16.6]) by mx.google.com with ESMTP id c22si1797563ika.2007.06.04.15.20.31; Mon, 04 Jun 2007 15:20:37 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of avalon.telekom.lv designates 194.8.16.6 as permitted sender) Subject: Undeliverable mail: =?ISO-8859-13?Q?Atbalsta_l=FBgums?= From: To: Date: Tue, 05 Jun 2007 01:20:30 +0300 Message-ID: X-MAPI-Message-Class: REPORT.IPM.Note.NDR MIME-Version: 1.0 Content-Type: multipart/report; report-type="delivery-status"; boundary="_===38387797====avalon.telekom.lv===_" --_===38387797====avalon.telekom.lv===_ Content-Type: text/plain; charset="utf-8" Failed to deliver to 'ilona.kalnina@citrus.lv' SMTP module(domain [10.2.9.112]) reports: host 10.2.9.112 says: 550 5.1.1 User unknown --_===38387797====avalon.telekom.lv===_ Content-Type: message/delivery-status Reporting-MTA: dns; avalon.telekom.lv Original-Recipient: rfc822; Final-Recipient: rfc822; Action: failed Status: 5.0.0 --_===38387797====avalon.telekom.lv===_ Content-Type: message/rfc822 Received: from ug-out-1314.google.com ([66.249.92.174] verified) by avalon.telekom.lv (CommuniGate Pro SMTP 5.0.8) with ESMTP id 38387776 for ilona.kalnina@citrus.lv; Tue, 05 Jun 2007 01:20:10 +0300 Received: by ug-out-1314.google.com with SMTP id y2so152uge for ; Mon, 04 Jun 2007 15:19:54 -0700 (PDT) DKIM-Signature: a=rsa-sha1; c=relaxed/relaxed; d=gmail.com; s=beta; h=domainkey-signature:received:received:message-id:date:from:to:subject:mime-version:content-type; b=l10L7A+KF49Pwyz92+DFPA/wZLu/uOlsEYg0PlwTfaVpXI/OKFJXSfhw1seTSbKWTnnQK60/hVdRqvdzBuGCQaZo5fkdhRFVQ6U24aBna+4L3tRyROlpOwVVNcWvdZydaJPuRWf8XLVJjy0z/850mX9tlCk8vdFOcAMzoS+/YwU= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=beta; h=received:message-id:date:from:to:subject:mime-version:content-type; b=epPNHV4IgrC3VhiIdXBXrbxBObboO2zqkB9gca8ZMpQBaH6TDRIhpFzukgJdEZBQHQih2W1trVQ1qPDYJsH3vz0IN5jiGbREfmqobCtrKR36zMw4sJw11YLLSS0j7ej4dJhwg7Vt7YLSM4fXtqsNuODv1ykPcEEBuxTsWlD8XW8= Received: by 10.67.32.16 with SMTP id k16mr3381783ugj.1180995594284; Mon, 04 Jun 2007 15:19:54 -0700 (PDT) Received: by 10.66.225.19 with HTTP; Mon, 4 Jun 2007 15:19:54 -0700 (PDT) Message-ID: Date: Tue, 5 Jun 2007 01:19:54 +0300 From: "Agris Ameriks" To: ilona.kalnina@citrus.lv Subject: =?ISO-8859-13?Q?Atbalsta_l=FBgums?= MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="----=_Part_13894_24991589.1180995594034" ------=_Part_13894_24991589.1180995594034 Content-Type: text/plain; charset=ISO-8859-13; format=flowed Content-Transfer-Encoding: base64 Content-Disposition: inline TGFiZGllbiEKCjE1LnNlcHRlbWJy7iBGaXptYXR1IGF0YmFsc3RhIGZvbmRzIHLua29zIGphdW5p ZfB1IGJ1cnpp8nUgIlRhdmEgcGFzYXVsZSEiLgoKUGFz4mt1bXMgbm90aWtzIFLuZ2FzIERvbWVz IEl6Z2zudO5iYXMsIGphdW5hdG5lcyB1biBzcG9ydGEKZGVwYXJ0YW1lbnRhIHLua290YWriIEph dW5pZfB1IG3nbmXwYSBpZXR2YXJvcy4gUu5nYXMgRG9tZSBwaWXw7WlyCjQnMDAwIExzIGzuZHpm aW5hbnPnanVtdS4KClbnbGFtaWVzIGz7Z3QgSvtzdSBwYWzuZHruYnUg8O4gcHJvamVrdGEg7nN0 ZW5v8GFu4i4KClPua+JrcyBwcm9qZWt0YSBhcHJha3N0cyBwaWV2aWVub3RzIHBpZWxpa3Vt4i4K CgotLSAKQXIgY2ll8nUsCkFncmlzIEFtZXJpa3MKRml6bWF0dSBhdGJhbHN0YSBmb25kcyBwcmll a/Bz52TndOJqcwpNb2IudGVsLiAyIDY0NjExMDEKRS1wYXN0czogQWdyaXMuQW1lcmlrc0BnbWFp bC5jb20K ------=_Part_13894_24991589.1180995594034 Content-Type: application/pdf; name="Citrus_Solutions.pdf" Content-Transfer-Encoding: base64 Content-Disposition: attachment; filename="Citrus_Solutions.pdf" X-Attachment-Id: f_f2ji9xzu MzE3MiAwMDAwMCBuDQowMDAwNzI2OTE4IDAwMDAwIG4NCnRyYWlsZXINCjw8L1NpemUgMzQ2Pj4N CnN0YXJ0eHJlZg0KMTE2DQolJUVPRg0KAttachmentTruncated ------=_Part_13894_24991589.1180995594034-- --_===38387797====avalon.telekom.lv===_-- schleuder-3.6.0/spec/fixtures/mails/bounces/tt_bounce_08.txt.eml000066400000000000000000000036711401002544500246540ustar00rootroot00000000000000Delivered-To: agris.ameriks@gmail.com Received: by 10.67.102.1 with SMTP id e1cs83816ugm; Mon, 17 Sep 2007 13:18:52 -0700 (PDT) Received: by 10.66.242.19 with SMTP id p19mr7552403ugh.1190060332137; Mon, 17 Sep 2007 13:18:52 -0700 (PDT) Return-Path: <> Received: by 10.66.242.19 with SMTP id p19mr10626800ugh; Mon, 17 Sep 2007 13:18:52 -0700 (PDT) Message-ID: <0014850b2bf1043a5a835bbd57c45e@googlemail.com> From: Mail Delivery Subsystem To: agris.ameriks@gmail.com Subject: Delivery Status Notification (Failure) Date: Mon, 17 Sep 2007 13:18:52 -0700 (PDT) This is an automatically generated Delivery Status Notification Delivery to the following recipient failed permanently: jauatkales@gmial.com Technical details of permanent failure: TEMP_FAILURE: Could not initiate SMTP conversation with any hosts: [gmial.com (1): Connection timed out] ----- Original message ----- Received: by 10.66.242.19 with SMTP id p19mr3910432ugh.1189785128812; Fri, 14 Sep 2007 08:52:08 -0700 (PDT) Received: by 10.67.102.1 with HTTP; Fri, 14 Sep 2007 08:52:08 -0700 (PDT) Message-ID: Date: Fri, 14 Sep 2007 18:52:08 +0300 From: "Agris Ameriks" To: Agris.Ameriks@gmail.com Subject: =?ISO-8859-13?Q?prof._Ivars_L=E2cis_uzst=E2sies_ar_lekciju?= MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="----=_Part_868_30357988.1189785128799" ------=_Part_868_30357988.1189785128799 Content-Type: text/plain; charset=ISO-8859-13 Content-Transfer-Encoding: base64 Content-Disposition: inline TGFiZGllbiEKCk5vc/t0dSBwcmVzZXMgcmVs7nppIHBhciBwYXPia3VtdSAxNS5zZXB0ZW1icu4g RXNwbGFu4mTnLgoKLS0gCkFyIGNpZfJ1LApBZ3JpcyBBbWVyaWtzCk1vYi50ZWwuIDIgNjQ2MTEw MQpFLXBhc3RzOiBBZ3Jpcy5BbWVyaWtzQGdtYWlsLmNvbQo= ------=_Part_868_30357988.1189785128799 Content-Type: application/msword; name="relize_rektori.doc" ----- Message truncated ----- schleuder-3.6.0/spec/fixtures/mails/bounces/tt_bounce_09.txt.eml000066400000000000000000000036671401002544500246620ustar00rootroot00000000000000Delivered-To: agris.ameriks@gmail.com Received: by 10.67.102.1 with SMTP id e1cs79686ugm; Mon, 17 Sep 2007 11:17:15 -0700 (PDT) Received: by 10.66.242.19 with SMTP id p19mr7441638ugh.1190053034458; Mon, 17 Sep 2007 11:17:14 -0700 (PDT) Return-Path: <> Received: by 10.66.242.19 with SMTP id p19mr10490766ugh; Mon, 17 Sep 2007 11:17:14 -0700 (PDT) Message-ID: <0014850b2bf1043a58d061fe5bc312@googlemail.com> From: Mail Delivery Subsystem To: agris.ameriks@gmail.com Subject: Delivery Status Notification (Failure) Date: Mon, 17 Sep 2007 11:17:14 -0700 (PDT) This is an automatically generated Delivery Status Notification Delivery to the following recipient failed permanently: gintsgrube@pop.ml.lv Technical details of permanent failure: TEMP_FAILURE: Could not initiate SMTP conversation with any hosts: [pop.ml.lv (1): Connection dropped] ----- Original message ----- Received: by 10.66.242.19 with SMTP id p19mr3910432ugh.1189785128812; Fri, 14 Sep 2007 08:52:08 -0700 (PDT) Received: by 10.67.102.1 with HTTP; Fri, 14 Sep 2007 08:52:08 -0700 (PDT) Message-ID: Date: Fri, 14 Sep 2007 18:52:08 +0300 From: "Agris Ameriks" To: Agris.Ameriks@gmail.com Subject: =?ISO-8859-13?Q?prof._Ivars_L=E2cis_uzst=E2sies_ar_lekciju?= MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="----=_Part_868_30357988.1189785128799" ------=_Part_868_30357988.1189785128799 Content-Type: text/plain; charset=ISO-8859-13 Content-Transfer-Encoding: base64 Content-Disposition: inline TGFiZGllbiEKCk5vc/t0dSBwcmVzZXMgcmVs7nppIHBhciBwYXPia3VtdSAxNS5zZXB0ZW1icu4g RXNwbGFu4mTnLgoKLS0gCkFyIGNpZfJ1LApBZ3JpcyBBbWVyaWtzCk1vYi50ZWwuIDIgNjQ2MTEw MQpFLXBhc3RzOiBBZ3Jpcy5BbWVyaWtzQGdtYWlsLmNvbQo= ------=_Part_868_30357988.1189785128799 Content-Type: application/msword; name="relize_rektori.doc" ----- Message truncated ----- schleuder-3.6.0/spec/fixtures/mails/bounces/tt_bounce_10.txt.eml000066400000000000000000000162331401002544500246430ustar00rootroot00000000000000Delivered-To: agris.ameriks@gmail.com Received: by 10.67.102.1 with SMTP id e1cs29105ugm; Sat, 15 Sep 2007 09:07:11 -0700 (PDT) Received: by 10.86.84.5 with SMTP id h5mr2204525fgb.1189872431018; Sat, 15 Sep 2007 09:07:11 -0700 (PDT) Return-Path: <> Received: from mail.studio7.lv ([159.148.225.2]) by mx.google.com with ESMTP id 13si4519655fks.2007.09.15.09.07.10; Sat, 15 Sep 2007 09:07:10 -0700 (PDT) Received-SPF: neutral (google.com: 159.148.225.2 is neither permitted nor denied by best guess record for domain of mail.studio7.lv) client-ip=159.148.225.2; Authentication-Results: mx.google.com; spf=neutral (google.com: 159.148.225.2 is neither permitted nor denied by best guess record for domain of mail.studio7.lv) smtp.mail= Received: by mail.studio7.lv (Postfix) id 7079F1088055; Sat, 15 Sep 2007 19:07:08 +0300 (EEST) Date: Sat, 15 Sep 2007 19:07:08 +0300 (EEST) From: MAILER-DAEMON@mail.studio7.lv (Mail Delivery System) Subject: Undelivered Mail Returned to Sender To: agris.ameriks@gmail.com MIME-Version: 1.0 Content-Type: multipart/report; report-type=delivery-status; boundary="8BCE21088059.1189872428/mail.studio7.lv" Message-Id: <20070915160708.7079F1088055@mail.studio7.lv> This is a MIME-encapsulated message. --8BCE21088059.1189872428/mail.studio7.lv Content-Description: Notification Content-Type: text/plain This is the Postfix program at host mail.studio7.lv. I'm sorry to have to inform you that your message could not be delivered to one or more recipients. It's attached below. For further assistance, please send mail to If you do so, please include this problem report. You can delete your own text from the attached returned message. The Postfix program : temporary failure --8BCE21088059.1189872428/mail.studio7.lv Content-Description: Delivery report Content-Type: message/delivery-status Reporting-MTA: dns; mail.studio7.lv X-Postfix-Queue-ID: 8BCE21088059 X-Postfix-Sender: rfc822; agris.ameriks@gmail.com Arrival-Date: Fri, 14 Sep 2007 18:52:25 +0300 (EEST) Final-Recipient: rfc822; info.rietumuradio.lv@mail.studio7.lv Action: failed Status: 4.0.0 Diagnostic-Code: X-Postfix; temporary failure --8BCE21088059.1189872428/mail.studio7.lv Content-Description: Undelivered Message Content-Type: message/rfc822 Received: from localhost (localhost.localdomain [127.0.0.1]) by mail.studio7.lv (Postfix) with ESMTP id 8BCE21088059 for ; Fri, 14 Sep 2007 18:52:25 +0300 (EEST) X-Virus-Scanned: amavisd-new at studio7.lv Received: from mail.studio7.lv ([127.0.0.1]) by localhost (smtp.studio7.lv [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id ptzaz7um-NBV for ; Fri, 14 Sep 2007 18:52:23 +0300 (EEST) Received: from hu-out-0506.google.com (hu-out-0506.google.com [72.14.214.227]) by mail.studio7.lv (Postfix) with ESMTP id 9F8D2108806D for ; Fri, 14 Sep 2007 18:52:22 +0300 (EEST) Received: by hu-out-0506.google.com with SMTP id 38so472432huc for ; Fri, 14 Sep 2007 08:52:21 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=beta; h=domainkey-signature:received:received:message-id:date:from:to:subject:mime-version:content-type; bh=4vXa1w6DKyZv8zm1ehZCNcwq4zu82fUl9OQIU6HbeGE=; b=rswuEvzRFbiKcOsstWjGjv1coaMxHwvSVfu8tIn4I9K3C/JY6JK2zK6C2vOPc9DUgaCyFxnXsv7Vf4ESuAcMTaqP3RCabN//lJ9YGixCxvdTZhgaS9vs9Ze6WV68Mw3lCB1eg5QC7CmhHlegDpAtBWV/NLqAPa9WiSun+T5eFxE= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=beta; h=received:message-id:date:from:to:subject:mime-version:content-type; b=dsax+33YeZDwUJY8uMkbOIOiBLaklYI33wM+tVcxaiESRe8TbTgOvPhQyW6x45knhFvyR9PNE7lDpq3Xz00OMMT6UnM9wRA9q7U0Pd2Vr2+lCw4DcXyfCo/PhBdYydODibWr//M0WmU9eL/S9zLSMW87gZPe0v4PNFd4hQSev9w= Received: by 10.66.242.19 with SMTP id p19mr3910432ugh.1189785128812; Fri, 14 Sep 2007 08:52:08 -0700 (PDT) Received: by 10.67.102.1 with HTTP; Fri, 14 Sep 2007 08:52:08 -0700 (PDT) Message-ID: Date: Fri, 14 Sep 2007 18:52:08 +0300 From: "Agris Ameriks" To: Agris.Ameriks@gmail.com Subject: =?ISO-8859-13?Q?prof._Ivars_L=E2cis_uzst=E2sies_ar_lekciju?= MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="----=_Part_868_30357988.1189785128799" ------=_Part_868_30357988.1189785128799 Content-Type: text/plain; charset=ISO-8859-13 Content-Transfer-Encoding: base64 Content-Disposition: inline TGFiZGllbiEKCk5vc/t0dSBwcmVzZXMgcmVs7nppIHBhciBwYXPia3VtdSAxNS5zZXB0ZW1icu4g RXNwbGFu4mTnLgoKLS0gCkFyIGNpZfJ1LApBZ3JpcyBBbWVyaWtzCk1vYi50ZWwuIDIgNjQ2MTEw MQpFLXBhc3RzOiBBZ3Jpcy5BbWVyaWtzQGdtYWlsLmNvbQo= ------=_Part_868_30357988.1189785128799 Content-Type: application/msword; name="relize_rektori.doc" Content-Transfer-Encoding: base64 Content-Disposition: attachment; filename="relize_rektori.doc" X-Attachment-Id: f_f6kvbbns 0M8R4KGxGuEAAAAAAAAAAAAAAAAAAAAAPgADAP7/CQAGAAAAAAAAAAAAAAABAAAALAAAAAAAAAAA EAAALgAAAAEAAAD+////AAAAACsAAAD///////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////s pcEAW4AJBAAA8BK/AAAAAAAAEAAAAAAACAAAEhQAAA4AYmpiaqz6rPoAAAAAAAAAAAAAAAAAAAAA AAAJBBYANBYAAM6QAQDOkAEApAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD//w8AAAAA AAAAAAD//w8AAAAAAAAAAAD//w8AAAAAAAAAAAAAAAAAAAAAALcAAAAAAJIFAAAAAAAAkgUAANUS AAAAAAAA1RIAAAAAAADVEgAAAAAAANUSAAAAAAAA1RIAABQAAAAAAAAAAAAAAP////8AAAAA6RIA AAAAAADpEgAAAAAAAOkSAAAAAAAA6RIAAAwAAAD1EgAADAAAAOkSAAAAAAAArxkAADABAAABEwAA AAAAAAETAAAAAAAAARMAAAAAAAABEwAAAAAAAAETAAAAAAAA3BMAAAAAAADcEwAAAAAAANwTAAAA AAAAIhkAAAIAAAAkGQAAAAAAACQZAAAAAAAAJBkAAAAAAAAkGQAAAAAAACQZAAAAAAAAJBkAACQA AADfGgAAogIAAIEdAAA2AAAASBkAACEAAAAAAAAAAAAAAAAAAAAAAAAA1RIAAAAAAADcEwAAAAAA AAAAAAAAAAAAAAAAAAAAAADcEwAAAAAAANwTAAAAAAAA3BMAAAAAAADcEwAAAAAAAEgZAAAAAAAA AAAAAAAAAADVEgAAAAAAANUSAAAAAAAAARMAAAAAAAAAAAAAAAAAAAETAADbAAAAaRkAABYAAADa GAAAAAAAANoYAAAAAAAA2hgAAAAAAADcEwAAcgQAANUSAAAAAAAAARMAAAAAAADVEgAAAAAAAAET AAAAAAAAIhkAAAAAAAAAAAAAAAAAANoYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAA3BMAAAAAAAAiGQAAAAAAAAAAAAAAAAAA2hgAAAAAAAAAAAAA AAAAANoYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA2hgAAAAAAAABEwAAAAAAAP////8AAAAAEA+LEuf2 xwEAAAAAAAAAAOkSAAAAAAAAThgAAGoAAADaGAAAAAAAAAAAAAAAAAAADhkAABQAAAB/GQAAMAAA AK8ZAAAAAAAA2hgAAAAAAAC3HQAAAAAAALgYAAAiAAAAtx0AAAAAAADaGAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAALcdAAAAAAAAAAAAAAAAAADVEgAAAAAAANoYAAA0AAAA3BMAAAAAAADcEwAAAAAAANoY AAAAAAAA3BMAAAAAAADcEwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3BMA --8BCE21088059.1189872428/mail.studio7.lv-- schleuder-3.6.0/spec/fixtures/mails/bounces/tt_bounce_11.txt.eml000066400000000000000000001104051401002544500246400ustar00rootroot00000000000000Delivered-To: agris.ameriks@gmail.com Received: by 10.67.102.1 with SMTP id e1cs7276ugm; Fri, 14 Sep 2007 08:52:48 -0700 (PDT) Received: by 10.78.146.11 with SMTP id t11mr1168394hud.1189785168336; Fri, 14 Sep 2007 08:52:48 -0700 (PDT) Return-Path: <> Received: from mao.leta.lv (mao.leta.lv [62.85.110.238]) by mx.google.com with ESMTP id s36si384903hub.2007.09.14.08.52.47; Fri, 14 Sep 2007 08:52:48 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of mao.leta.lv designates 62.85.110.238 as permitted sender) client-ip=62.85.110.238; Authentication-Results: mx.google.com; spf=pass smtp.mail= Received: from letaexc.leta.lv (letaexc.leta.lv [192.168.0.2]) by mao.leta.lv (Postfix) with ESMTP id 6CE9B1C1F121 for ; Fri, 14 Sep 2007 18:52:46 +0300 (EEST) Received: by letaexc.leta.lv with Internet Mail Service (5.5.2657.72) id ; Fri, 14 Sep 2007 18:53:01 +0300 Message-ID: From: System Administrator To: agris.ameriks@gmail.com Subject: =?WINDOWS-1257?Q?Undeliverable=3A_prof=2E_Ivars_L=E2cis_uzst=E2?= =?WINDOWS-1257?Q?sies_ar_lekciju?= Date: Fri, 14 Sep 2007 18:53:01 +0300 MIME-Version: 1.0 X-Mailer: Internet Mail Service (5.5.2657.72) X-MS-Embedded-Report: Content-Type: multipart/mixed; boundary="----_=_NextPart_000_01C7F6E7.540B3540" This message is in MIME format. Since your mail reader does not understand this format, some or all of this message may not be legible. ------_=_NextPart_000_01C7F6E7.540B3540 Content-Type: text/plain; charset="WINDOWS-1257" Content-Transfer-Encoding: quoted-printable Your message To: Agris.Ameriks@gmail.com Subject: prof. Ivars L=E2cis uzst=E2sies ar lekciju Sent: Fri, 14 Sep 2007 18:52:08 +0300 did not reach the following recipient(s): M=E2rti=F2=F0 Luka=F0evi=E8s on Fri, 14 Sep 2007 18:52:54 +0300 The recipient was unavailable to take delivery of the message The MTS-ID of the original message is: c=3Dus;a=3D ;p=3Dleta;l=3DLETAEXC0709141552S7ZB4DDP MSEXCH:MSExchangeMTA:LETA:LETAEXC ------_=_NextPart_000_01C7F6E7.540B3540 Content-Type: message/rfc822 Message-ID: From: Agris Ameriks To: Agris.Ameriks@gmail.com Subject: =?WINDOWS-1257?Q?prof=2E_Ivars_L=E2cis_uzst=E2sies_ar_lekciju?= Date: Fri, 14 Sep 2007 18:52:08 +0300 MIME-Version: 1.0 X-Mailer: Internet Mail Service (5.5.2657.72) X-MS-Embedded-Report: Content-Type: multipart/mixed; boundary="----_=_NextPart_002_01C7F6E7.540B3540" ------_=_NextPart_002_01C7F6E7.540B3540 Content-Type: text/plain; charset="WINDOWS-1257" Content-Transfer-Encoding: quoted-printable Labdien! Nos=FBtu preses rel=EEzi par pas=E2kumu 15.septembr=EE Esplan=E2d=E7. --=20 Ar cie=F2u, Agris Ameriks Mob.tel. 2 6461101 E-pasts: Agris.Ameriks@gmail.com ------_=_NextPart_002_01C7F6E7.540B3540 Content-Type: application/msword; name="relize_rektori.doc" Content-Transfer-Encoding: base64 Content-Disposition: attachment; filename="relize_rektori.doc" 0M8R4KGxGuEAAAAAAAAAAAAAAAAAAAAAPgADAP7/CQAGAAAAAAAAAAAAAAABAAAALAAAAAAAAAAA EAAALgAAAAEAAAD+////AAAAACsAAAD///////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////s pcEAW4AJBAAA8BK/AAAAAAAAEAAAAAAACAAAEhQAAA4AYmpiaqz6rPoAAAAAAAAAAAAAAAAAAAAA AAAJBBYANBYAAM6QAQDOkAEApAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD//w8AAAAA AAAAAAD//w8AAAAAAAAAAAD//w8AAAAAAAAAAAAAAAAAAAAAALcAAAAAAJIFAAAAAAAAkgUAANUS AAAAAAAA1RIAAAAAAADVEgAAAAAAANUSAAAAAAAA1RIAABQAAAAAAAAAAAAAAP////8AAAAA6RIA AAAAAADpEgAAAAAAAOkSAAAAAAAA6RIAAAwAAAD1EgAADAAAAOkSAAAAAAAArxkAADABAAABEwAA AAAAAAETAAAAAAAAARMAAAAAAAABEwAAAAAAAAETAAAAAAAA3BMAAAAAAADcEwAAAAAAANwTAAAA AAAAIhkAAAIAAAAkGQAAAAAAACQZAAAAAAAAJBkAAAAAAAAkGQAAAAAAACQZAAAAAAAAJBkAACQA AADfGgAAogIAAIEdAAA2AAAASBkAACEAAAAAAAAAAAAAAAAAAAAAAAAA1RIAAAAAAADcEwAAAAAA AAAAAAAAAAAAAAAAAAAAAADcEwAAAAAAANwTAAAAAAAA3BMAAAAAAADcEwAAAAAAAEgZAAAAAAAA AAAAAAAAAADVEgAAAAAAANUSAAAAAAAAARMAAAAAAAAAAAAAAAAAAAETAADbAAAAaRkAABYAAADa GAAAAAAAANoYAAAAAAAA2hgAAAAAAADcEwAAcgQAANUSAAAAAAAAARMAAAAAAADVEgAAAAAAAAET AAAAAAAAIhkAAAAAAAAAAAAAAAAAANoYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAA3BMAAAAAAAAiGQAAAAAAAAAAAAAAAAAA2hgAAAAAAAAAAAAA AAAAANoYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA2hgAAAAAAAABEwAAAAAAAP////8AAAAAEA+LEuf2 xwEAAAAAAAAAAOkSAAAAAAAAThgAAGoAAADaGAAAAAAAAAAAAAAAAAAADhkAABQAAAB/GQAAMAAA AK8ZAAAAAAAA2hgAAAAAAAC3HQAAAAAAALgYAAAiAAAAtx0AAAAAAADaGAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAALcdAAAAAAAAAAAAAAAAAADVEgAAAAAAANoYAAA0AAAA3BMAAAAAAADcEwAAAAAAANoY AAAAAAAA3BMAAAAAAADcEwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3BMA AAAAAADcEwAAAAAAANwTAAAAAAAASBkAAAAAAABIGQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAA2hgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANwTAAAA AAAA3BMAAAAAAADcEwAAAAAAAK8ZAAAAAAAA3BMAAAAAAADcEwAAAAAAANwTAAAAAAAA3BMAAAAA AAAAAAAAAAAAAP////8AAAAA/////wAAAAD/////AAAAAAAAAAAAAAAA/////wAAAAD/////AAAA AP////8AAAAA/////wAAAAD/////AAAAAP////8AAAAA/////wAAAAD/////AAAAAP////8AAAAA /////wAAAAD/////AAAAAP////8AAAAA/////wAAAAD/////AAAAALcdAAAAAAAA3BMAAAAAAADc EwAAAAAAANwTAAAAAAAA3BMAAAAAAADcEwAAAAAAANwTAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADcEwAAAAAAANwTAAAAAAAA3BMA AAAAAACSBQAACQwAAJsRAAA6AQAABQASAQAACQQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADIAMAAw ADcALgBnAGEAZABhACAAMQA0AC4AcwBlAHAAdABlAG0AYgByAGkAcwAuAA0ASQBuAGYAbwByAG0A AQFjAGkAagB1ACAAcwBhAGcAYQB0AGEAdgBvAGoAYQAgAEEAZwByAGkAcwAgAEEAbQBlAHIAaQBr AHMADQAxADUALgBzAGUAcAB0AGUAbQBiAHIAKwEgAGUAawBzAC0AcgBlAGsAdABvAHIAcwAgAHAA cgBvAGYALgAgAEkAdgBhAHIAcwAgAEwAAQFjAGkAcwAgAGwAYQBzACsBcwAgAGwAZQBrAGMAaQBq AHUALgANAFMAdAB1AGQAZQBuAHQAdQAgAFAAAQFyAHQAaQBqAGEAIABpAGUAdAB2AGEAcgBvAHMA IAAxADUALgBzAGUAcAB0AGUAbQBiAHIAKwEgAEUAcwBwAGwAYQBuAAEBZAATASAAcAByAG8AZgAu ACAASQAuAEwAAQFjAGkAcwAgAHUAegBzAHQAAQFzAGkAZQBzACAAYQByACAAbABlAGsAYwBpAGoA dQAgABwgYAE3AWkAdAB1AG0AcwAgAHUAbgAgACsBcwB0AGUAbgArAWIAYQAdICwAIABrAHUAcgAg AHMAdAABAXMAdAArAXMAIABwAGEAcgAgAG8AcAB0AGkAawBhAHMAIABpAGwAawF6AGkAagABAW0A IAB1AG4AIABjAGkAdAABAW0AIABwAGEAcgABAWQAKwFiAAEBbQAsACAAawBhAHMAIABzAGEAaQBz AHQAKwF0AGEAcwAgAGEAcgAgAG8AcAB0AGkAawB1ACAAdQBuACAAcgBlAGQAegBpAC4ADQBQAHIA bwBmAC4AIABBAG4AZAByAGUAagBzACAAQwATAWIAZQByAHMAIABzAHQAAQFzAHQAKwFzACAAcABh AHIAIABtAGEAZwBuABMBdABpAHMAawBvACAAYgBhAGsAdAATAXIAaQBqAHUAIABwAGkAZQBsAGkA ZQB0AG8AagB1AG0AdQAsACAAdQB6AGIAawF2AGkALAAgAGQAYQByAGIAKwFiAGEAcwAgAHAAcgBp AG4AYwBpAHAAaQBlAG0ALgANAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAANgsA AAAQAADKEQAAzBEAAM4RAAAyEgAAdhIAAM4TAAASFAAA/Pr89vz28vbuAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAYWaHEWDgAABhZonDXIAAAGFmhUZYUAAANVCAEGFmh9PrcACQAIAAAyCAAA fAgAAPAIAAB0CgAANgsAAM4QAADOEQAAeBIAAM4TAAASFAAA+gAAAAAAAAAAAAAAAPoAAAAAAAAA AAAAAAD6AAAAAAAAAAAAAAAA+gAAAAAAAAAAAAAAAPoAAAAAAAAAAAAAAAD6AAAAAAAAAAAAAAAA +gAAAAAAAAAAAAAAAPoAAAAAAAAAAAAAAAD1AAAAAAAAAAAAAAAA9QAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAZ2RUZYUAAAQAAGdkfT63AAAKSQBsAGcAbwBu AGkAcwAgAFYAaQBsAGsAcwAgAHMAdAABAXMAdAArAXMAIABwAGEAcgAgAGEAcABzAHQAAQFrADwB aQBlAG0AIABrAG8AcwBtAG8AcwABASwAIABpAGUAcwBwABMBagBhAG0AAQFzACAAZAB6ACsBdgAr AWIAYQBzACAAcABhAHMAdAABAXYAEwFhAWEAbgBhAHMAIAB2AGkAZQB0AAEBbQAgAHUAbgAgAG4A bwBzAGEAYwArAWoAdQBtAGkAZQBtAC4ADQBKAHUAcgBpAHMAIABgAXQAZQBpAG4AYgBlAHIAZwBz ACAAcwB0AAEBcwB0ACsBcwAgAHAAYQByACAAcABhAGEBbABhAGkAawAgAHAAYQBzAGEAdQBsABMB IAAcIHQAbwBwAAEBHSAgAGUAcwBvAGEBYQBqAAEBbQAgAHAAbwBsAGkAbQATAXoAZQBzACAANwET AWQAEwFtACAAdQBuACAAcwBrAGEAaQBkAHIAbwBzACwAIABrAGEAcwAgAHQAAQFzACAAaQByACAA dQBuACAAawABAXAAEwFjACAAdAABAXMAIABpAHIAIAB0AGkAawAgAGwAYQBiAGEAcwAuAA0ATABl AGsAYwBpAGoAYQBzACAAaQByACAAYgBlAHoAIABtAGEAawBzAGEAcwAhACAAQQB0AG4AAQFjAGkA ZQB0ACAAdQBuACAAaQB6AGcAbAArAXQAbwBqAGEAdABpAGUAcwAhACAATABlAGsAYwBpAGoAYQBz ACAAbgBvAHQAaQBrAHMAIABuAG8AIAAxADUAOgAwADAAIAATICAAMQA5ADoAMAAwAC4ADQBMAGkA ZQBsAHMAIABwAGEAbABkAGkAZQBzACAAbQBrAXMAdQAgAGEAdABiAGEAbABzAHQAKwF0AAEBagBp AGUAbQA6ACAAUgArAWcAYQBzACAARABvAG0AZQBpACwAIABBAEMAQwBFAE4AVABVAFIARQAsACAA UgBJAE0ASQAuACAASwABASAAYQByACsBIABwAGEAbABkAGkAZQBzACAAZAByAGEAdQBnAGkAZQBt AC4AbAB2ACwAIABMAFQAVgAsACAARABJAEUATgBBACwAIAA1AG0AaQBuACwAIABLAG8AbgB0AGkA IABCAHUAcwBzACwAIABBAGwAZABhAHIAaQBzACwAIABEAG8AdQBiAGwAZQAgAEMAbwBmAGYAZQBl ACwAIABQAHIAbwBXAGUAYgAsACAAUgArAWcAYQBzACAAWgBvAG8AZAABAXIAegBzAC4ADQBWAGEA aQByAAEBawAgAGkAbgBmAG8AIABwAGEAIAB0AAEBbAByAHUAbgBpADoAIAAyADYAMwAxADYANAAx ADMALgANAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMgAxkGgBOnBsQZcA H7DQLyCw4D0hsAgHIrAIByOQoAUkkKAFJbAAABewxAIYsMQCDJDEAgAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABqBA8AEgABAAsBDwAH AAMAAwADAAAABAAIAAAAmAAAAJ4AAACeAAAAngAAAJ4AAACeAAAAngAAAJ4AAACeAAAANgYAADYG AAA2BgAANgYAADYGAAA2BgAANgYAADYGAAA2BgAAdgIAAHYCAAB2AgAAdgIAAHYCAAB2AgAAdgIA AHYCAAB2AgAANgYAADYGAAA2BgAANgYAADYGAAA2BgAAPgIAADYGAAA2BgAANgYAADYGAAA2BgAA NgYAADYGAAA2BgAANgYAADYGAAA2BgAANgYAADYGAAA2BgAANgYAADYGAAA2BgAANgYAADYGAAA2 BgAANgYAADYGAAA2BgAANgYAADYGAAA2BgAANgYAAKgAAAA2BgAANgYAABYAAAA2BgAANgYAADYG AAA2BgAANgYAADYGAAA2BgAANgYAALgAAAA2BgAANgYAADYGAAA2BgAANgYAADYGAAA2BgAANgYA ADYGAAA2BgAANgYAADYGAABoAQAASAEAADYGAAA2BgAANgYAADYGAAA2BgAANgYAADYGAAA2BgAA NgYAADYGAAA2BgAANgYAADYGAAA2BgAANgYAADYGAAA2BgAANgYAADYGAAA2BgAANgYAADYGAAA2 BgAANgYAADYGAAA2BgAANgYAADYGAAA2BgAANgYAADYGAAA2BgAANgYAADYGAAA2BgAANgYAADYG AAA2BgAANgYAADYGAAA2BgAANgYAADYGAAA2BgAANgYAADYGAAA2BgAANgYAADYGAAA2BgAANgYA ADYGAAA2BgAANgYAADYGAAA2BgAANgYAADYGAAA2BgAANgYAADYGAAA2BgAANgYAADYGAAA2BgAA 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 AAAAAAAAAAAAAAAAFAIAAHRoZW1lL3RoZW1lL3RoZW1lTWFuYWdlci54bWxQSwECLQAUAAYACAAA ACEAlrWt4pYGAABQGwAAFgAAAAAAAAAAAAAAAADRAgAAdGhlbWUvdGhlbWUvdGhlbWUxLnhtbFBL AQItABQABgAIAAAAIQAN0ZCftgAAABsBAAAnAAAAAAAAAAAAAAAAAJsJAAB0aGVtZS90aGVtZS9f cmVscy90aGVtZU1hbmFnZXIueG1sLnJlbHNQSwUGAAAAAAUABQBdAQAAlgoAAAAAPD94bWwgdmVy c2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9InllcyI/Pg0KPGE6Y2xyTWFw IHhtbG5zOmE9Imh0dHA6Ly9zY2hlbWFzLm9wZW54bWxmb3JtYXRzLm9yZy9kcmF3aW5nbWwvMjAw Ni9tYWluIiBiZzE9Imx0MSIgdHgxPSJkazEiIGJnMj0ibHQyIiB0eDI9ImRrMiIgYWNjZW50MT0i YWNjZW50MSIgYWNjZW50Mj0iYWNjZW50MiIgYWNjZW50Mz0iYWNjZW50MyIgYWNjZW50ND0iYWNj ZW50NCIgYWNjZW50NT0iYWNjZW50NSIgYWNjZW50Nj0iYWNjZW50NiIgaGxpbms9ImhsaW5rIiBm b2xIbGluaz0iZm9sSGxpbmsiLz4AAAAApAMAABMAABYAAAUA/////wAIAAASFAAABgAAAAAIAAAS FAAABwAAAA8AAPA4AAAAAAAG8BgAAAACCAAAAgAAAAEAAAABAAAAAQAAAAIAAABAAB7xEAAAAP// AAAAAP8AgICAAPcAABAADwAC8JIAAAAQAAjwCAAAAAEAAAABBAAADwAD8DAAAAAPAATwKAAAAAEA CfAQAAAAAAAAAAAAAAAAAAAAAAAAAAIACvAIAAAAAAQAAAUAAAAPAATwQgAAABIACvAIAAAAAQQA AAAOAABTAAvwHgAAAL8BAAAQAMsBAAAAAP8BAAAIAAQDCQAAAD8DAQABAAAAEfAEAAAAAQAAAAAA AAAZAAAAJAAAACUAAAAvAAAAMAAAADUAAAA2AAAAPQAAAEsAAABWAAAAVwAAAFsAAABdAAAAYgAA AGMAAABoAAAAaQAAAG4AAABvAAAAdgAAAHgAAACAAAAAgQAAAIgAAACJAAAAkQAAAJ8AAACoAAAA qQAAAK0AAACvAAAAtgAAALcAAADAAAAAwQAAAMMAAADEAAAAywAAAM0AAADUAAAA2AAAAOAAAADj AAAA5gAAAOcAAADuAAAA8wAAAPoAAAD7AAAAAwEAAAcBAAAMAQAADQEAABYBAAAYAQAAGwEAABwB AAAlAQAAJgEAACgBAAApAQAALwEAADMBAAA4AQAAQAEAAEcBAABIAQAATgEAAE8BAABWAQAAWwEA AGUBAABmAQAAbwEAAHABAAB8AQAAfgEAAIQBAACGAQAAjgEAAI8BAACZAQAAmwEAAKIBAACjAQAA qAEAAKkBAACwAQAAtQEAAL8BAADAAQAAxwEAAMkBAADTAQAA1AEAANwBAADdAQAA6QEAAOoBAADw AQAA9AEAAAACAAACAgAABwIAAAgCAAASAgAAEwIAABoCAAAfAgAAJgIAACcCAAAuAgAAMAIAADQC AAA2AgAAPgIAAD8CAABIAgAASQIAAE4CAABSAgAAWgIAAFwCAABfAgAAYAIAAGMCAABkAgAAZgIA AGoCAABvAgAAcAIAAHMCAAB0AgAAdgIAAHcCAAB6AgAAewIAAIACAACCAgAAigIAAIsCAACNAgAA jgIAAJECAACSAgAAmAIAAJoCAACiAgAApgIAALMCAAC1AgAAvQIAAL4CAADEAgAA1wIAANwCAADd AgAA5AIAAOUCAADpAgAA6gIAAPgCAAD6AgAA/wIAAAADAAAFAwAAGAMAABoDAAAbAwAAHgMAAB8D AAAmAwAARgMAAEsDAABSAwAAWQMAAGoDAABwAwAAcgMAAHcDAAB4AwAAgAMAAIIDAACIAwAAkQMA AJgDAACaAwAAogMAAKYDAAAHABwABwAcAAcAHAAHABwABwAcAAcAHAAHABwABwAcAAcAHAAHABwA BwAcAAcAHAAHABwABwAcAAcAHAAHABwABwAcAAcAHAAHABwABwAcAAcAHAAHABwABwAcAAcAHAAH ABwABwAcAAcAHAAHABwABwAcAAcAHAAHABwABwAcAAcAHAAHABwABwAcAAcAHAAHABwABwAcAAcA HAAHABwABwAcAAcAHAAHABwABwAcAAcAHAAHABwABwAcAAcAHAAHABwABwAcAAcAHAAHABwABwAc AAcAHAAHABwABwAcAAcAHAAHABwABwAcAAcAHAAHABwABwAcAAcAHAAHABwABwAcAAcAHAAHABwA BwAcAAcAHAAHABwABwAcAAcAHAAHABwABwAcAAcAHAAHABwABwAcAAcAHAAHABwABwAcAAcAHAAH ABwABwAcAAcAHAAHABwABwAcAAcAHAAHABwABwAcAAcAHAAHABwABwAcAAcAHAAHAAQABwAAAAAA BAAAAAkAAABAAAAASgAAAAQBAAAGAQAA8QEAAPMBAABPAgAAUQIAAKMCAAClAgAAtQIAANYCAACC AwAAowMAAKYDAAAHADMABwAzAAcAMwAHADMABwAzAAcAMwAHADMABwAEAAcAAAAAAGECAADWAgAA 1wIAAKMDAACmAwAAAwAEAAMABAAHAAcAAAAEAAAACAAAAOUAAAAAAAAABAAAAHEWDgAvfRUA3lJi AFRlhQBsQZcAfT63AJw1yAAAAAAApAMAAKYDAAAAAAAAAQAAAP9AAYABAKIDAACiAwAAAEj8BbsA uwCiAwAAAAAAAKIDAAAAAAAAAhwAAAAAAAAAmwEAAKQDAACYAAAIAAAAAJgAABAAAAAA//8BAAAA BwBVAG4AawBuAG8AdwBuAP//AQAIAAAAAAAAAAAAAAD//wEAAAAAAP//AAACAP//AAAAAP//AAAC AP//AAAAAAUAAABHHpABugACAgYDBQQFAgMEhyoAIAAAAIAIAAAAAAAAAP8BAAAAAAAAVABpAG0A ZQBzACAATgBlAHcAIABSAG8AbQBhAG4AAAA1HpABAgAFBQECAQcGAgUHAAAAAAAAABAAAAAAAAAA AAAAAIAAAAAAUwB5AG0AYgBvAGwAAAAzLpABugACCwYEAgICAgIEhyoAIAAAAIAIAAAAAAAAAP8B AAAAAAAAQQByAGkAYQBsAAAANy6QAboAAg8FAgICBAMCBO8CAKB7IABAAAAAAAAAAACfAAAAAAAA AEMAYQBsAGkAYgByAGkAAABBHpABugAAAAAAAAAAAAAA7wIAoOsgAEIAAAAAAAAAAJ8AAAAAAAAA QwBhAG0AYgByAGkAYQAgAE0AYQB0AGgAAAAiAAQAcQiIGADw0AIAAGgBAAAAAKJ0uaazdLmmAAAA AAMAEQAAAIsAAAAZAwAAAQABAAAABAADkAYAAACLAAAAGQMAAAEAAQAAAAYAAAAAAAAAIQMA8BAA AAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAegBbQAtACBgTIwAAAAAAAAAAAAAAAAAACjAwAA owMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAIAAAAAAAAAAAAAMoNRAPAQAAgA/P0BAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACEhQ AAAAAAnw/w8BCCRQAADpBAAA////f////3////9/////f////3////9/////f30+twAABAAAMgAA AAAAAAAAAAAAAAAAAAAAAAAAACEEAAAAAAAAAAAAAAAAAAAAAAAAEBwAAAQAAAAAAAAAAAB4AAAA eAAAAAAAAAAAAAAAoAUAAP//EgAAAAAAAAAAAAAAAAAAAAMAQQBBAEEAAwBBAEEAQQAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD+/wAABQECAAAAAAAAAAAAAAAAAAAAAAABAAAA 4IWf8vlPaBCrkQgAKyez2TAAAABgAQAAEQAAAAEAAACQAAAAAgAAAJgAAAADAAAApAAAAAQAAACw AAAABQAAALwAAAAGAAAAyAAAAAcAAADUAAAACAAAAOQAAAAJAAAA8AAAABIAAAD8AAAACgAAABwB AAAMAAAAKAEAAA0AAAA0AQAADgAAAEABAAAPAAAASAEAABAAAABQAQAAEwAAAFgBAAACAAAA6QQA AB4AAAAEAAAAAAAAAB4AAAAEAAAAAAAAAB4AAAAEAAAAQUFBAB4AAAAEAAAAAAAAAB4AAAAEAAAA AAAAAB4AAAAIAAAATm9ybWFsAAAeAAAABAAAAEFBQQAeAAAABAAAADMAAAAeAAAAGAAAAE1pY3Jv c29mdCBPZmZpY2UgV29yZAAAAEAAAAAApvdfAgAAAEAAAAAAZOGr5PbHAUAAAAAACtkL5/bHAQMA AAABAAAAAwAAAIsAAAADAAAAGQMAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAA/v8AAAUBAgAAAAAAAAAAAAAAAAAAAAAAAQAAAALVzdWcLhsQ k5cIACss+a4wAAAA6AAAAAwAAAABAAAAaAAAAA8AAABwAAAABQAAAHwAAAAGAAAAhAAAABEAAACM AAAAFwAAAJQAAAALAAAAnAAAABAAAACkAAAAEwAAAKwAAAAWAAAAtAAAAA0AAAC8AAAADAAAAMkA AAACAAAA6QQAAB4AAAAEAAAAQUEAAAMAAAAGAAAAAwAAAAEAAAADAAAAowMAAAMAAAAAAAwACwAA AAAAAAALAAAAAAAAAAsAAAAAAAAACwAAAAAAAAAeEAAAAQAAAAEAAAAADBAAAAIAAAAeAAAABgAA AFRpdGxlAAMAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAEAAAACAAAAAwAAAAQAAAAFAAAABgAAAAcAAAAIAAAACQAAAAoAAAALAAAA /v///w0AAAAOAAAADwAAABAAAAARAAAAEgAAABMAAAAUAAAAFQAAABYAAAAXAAAAGAAAABkAAAAa AAAA/v///xwAAAAdAAAAHgAAAB8AAAAgAAAAIQAAACIAAAD+////JAAAACUAAAAmAAAAJwAAACgA AAApAAAAKgAAAP7////9////LQAAAP7////+/////v////////////////////////////////// //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// ////////////////UgBvAG8AdAAgAEUAbgB0AHIAeQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAABYABQH//////////wMAAAAGCQIAAAAAAMAAAAAAAABGAAAAAAAA AAAAAAAAUByOEuf2xwEvAAAAgAAAAAAAAAAxAFQAYQBiAGwAZQAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADgACAf////8FAAAA/////wAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAC3HQAAAAAAAFcAbwByAGQARABvAGMAdQBt AGUAbgB0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAaAAIBAQAAAP// ////////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADQWAAAAAAAABQBT AHUAbQBtAGEAcgB5AEkAbgBmAG8AcgBtAGEAdABpAG8AbgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAACgAAgECAAAABAAAAP////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAb AAAAABAAAAAAAAAFAEQAbwBjAHUAbQBlAG4AdABTAHUAbQBtAGEAcgB5AEkAbgBmAG8AcgBtAGEA dABpAG8AbgAAAAAAAAAAAAAAOAACAf///////////////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAACMAAAAAEAAAAAAAAAEAQwBvAG0AcABPAGIAagAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAASAAIA////////////////AAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///////// //////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAP///////////////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAEAAAD+//////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// ////////////AQD+/wMKAAD/////BgkCAAAAAADAAAAAAAAARicAAABNaWNyb3NvZnQgT2ZmaWNl IFdvcmQgOTctMjAwMyBEb2N1bWVudAAKAAAATVNXb3JkRG9jABAAAABXb3JkLkRvY3VtZW50LjgA 9DmycQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAA= ------_=_NextPart_002_01C7F6E7.540B3540-- ------_=_NextPart_000_01C7F6E7.540B3540-- schleuder-3.6.0/spec/fixtures/mails/bounces/tt_bounce_12_soft.txt.eml000066400000000000000000000032541401002544500256770ustar00rootroot00000000000000Delivered-To: agris.ameriks@gmail.com Received: by 10.67.102.1 with SMTP id e1cs22976ugm; Sat, 15 Sep 2007 00:47:40 -0700 (PDT) Received: by 10.35.36.13 with SMTP id o13mr3311239pyj.1189842459008; Sat, 15 Sep 2007 00:47:39 -0700 (PDT) Return-Path: <> Received: by 10.35.36.13 with SMTP id o13mr4245718pyj; Sat, 15 Sep 2007 00:47:39 -0700 (PDT) Message-ID: <00163600cfda043a27c91b990c7fbc@googlemail.com> From: Mail Delivery Subsystem To: agris.ameriks@gmail.com Subject: Delivery Status Notification (Delay) Date: Sat, 15 Sep 2007 00:47:39 -0700 (PDT) This is an automatically generated Delivery Status Notification THIS IS A WARNING MESSAGE ONLY. YOU DO NOT NEED TO RESEND YOUR MESSAGE. Delivery to the following recipient has been delayed: info@radioliepaja.lv Message will be retried for 2 more day(s) Technical details of temporary failure: TEMP_FAILURE: Could not initiate SMTP conversation with any hosts: [radioliepaja.lv. (50): Connection timed out] ----- Message header follows ----- Received: by 10.35.36.13 with SMTP id o13mr1865462pyj.1189751181221; Thu, 13 Sep 2007 23:26:21 -0700 (PDT) Received: by 10.35.73.12 with HTTP; Thu, 13 Sep 2007 23:26:20 -0700 (PDT) Message-ID: Date: Fri, 14 Sep 2007 09:26:20 +0300 From: "Agris Ameriks" To: Agris.Ameriks@gmail.com, "=?ISO-8859-13?Q?J=E2nis_Erts?=" Subject: =?UTF-8?Q?15.septembr=C4=AB_neaizmirstams_pas=C4=81kums!?= MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="----=_Part_979_8743786.1189751181201" ----- Message body suppressed ----- schleuder-3.6.0/spec/fixtures/mails/bounces/tt_bounce_13.txt.eml000066400000000000000000001326101401002544500246440ustar00rootroot00000000000000Delivered-To: agris.ameriks@gmail.com Received: by 10.35.73.12 with SMTP id a12cs13488pyl; Thu, 13 Sep 2007 23:26:29 -0700 (PDT) Received: by 10.66.184.17 with SMTP id h17mr3414064ugf.1189751188285; Thu, 13 Sep 2007 23:26:28 -0700 (PDT) Return-Path: <> Received: from LVAEI-EXCH.lvaei.lv (mail.lvaei.lv [217.199.123.22]) by mx.google.com with ESMTP id h7si1530964nfh.2007.09.13.23.26.27; Thu, 13 Sep 2007 23:26:28 -0700 (PDT) Received-SPF: pass (google.com: domain of LVAEI-EXCH.lvaei.lv designates 217.199.123.22 as permitted sender) client-ip=217.199.123.22; Authentication-Results: mx.google.com; spf=pass smtp.mail= From: postmaster@lvaei.lv To: agris.ameriks@gmail.com Date: Fri, 14 Sep 2007 09:46:02 +0300 MIME-Version: 1.0 Content-Type: multipart/report; report-type=delivery-status; boundary="9B095B5ADSN=_01C7DED0EB082C7600015D0ALVAEI?EXCH.lvaei" X-DSNContext: 7ce717b1 - 1158 - 00000002 - 00000000 Message-ID: Subject: Delivery Status Notification (Failure) This is a MIME-formatted message. Portions of this message may be unreadable without a MIME-capable mail program. --9B095B5ADSN=_01C7DED0EB082C7600015D0ALVAEI?EXCH.lvaei Content-Type: text/plain; charset=unicode-1-1-utf-7 This is an automatically generated Delivery Status Notification. Delivery to the following recipients failed. ilzeB@lvaei.lv --9B095B5ADSN=_01C7DED0EB082C7600015D0ALVAEI?EXCH.lvaei Content-Type: message/delivery-status Reporting-MTA: dns;LVAEI-EXCH.lvaei.lv Received-From-MTA: dns;py-out-1112.google.com Arrival-Date: Fri, 14 Sep 2007 09:46:01 +0300 Final-Recipient: rfc822;ilzeB@lvaei.lv Action: failed Status: 5.2.2 X-Display-Name: Ilze Bumane --9B095B5ADSN=_01C7DED0EB082C7600015D0ALVAEI?EXCH.lvaei Content-Type: message/rfc822 Received: from py-out-1112.google.com ([64.233.166.181]) by LVAEI-EXCH.lvaei.lv with Microsoft SMTPSVC(6.0.3790.1830); Fri, 14 Sep 2007 09:46:01 +0300 Received: by py-out-1112.google.com with SMTP id p76so1664020pyb for ; Thu, 13 Sep 2007 23:26:24 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=beta; h=domainkey-signature:received:received:message-id:date:from:to:subject:mime-version:content-type; bh=UkLIOLa7aKX8l2Co4lQQH3S/oEkmFQxnABs/uYG4J8E=; b=dhMd24LoSESYtapU28YxUj4cjlIH2FOLv3hAE6gBF/lf0FBNyhyKdAMOBd0BkaexqcRMBppWNOT/QgWReqjOXFj0fUKhR9scXK+HwKdYmHm1VVOOlKsdBTEvWKWTSJJ8f+TYkMaSbqXDvosZFJR903KYEw3sTPkP1+TDZmeXcao= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=beta; h=received:message-id:date:from:to:subject:mime-version:content-type; b=rJxPO+Tb+m374iu5R+K/cpKZcmXfs59lcztuwmbzM7Vdh5LVGb9P5pTbn8xlgyw0WH7iqUXGUWZxjJlQu+gbOwTHjcvKkcxoPeEXAlaW1XNma/PVQ30cC0BSmsDqZh12t1P3lqksap5ZgF1yTlsm+yZq6TiypiBYTa3L2uEEGvw= Received: by 10.35.36.13 with SMTP id o13mr1865462pyj.1189751181221; Thu, 13 Sep 2007 23:26:21 -0700 (PDT) Received: by 10.35.73.12 with HTTP; Thu, 13 Sep 2007 23:26:20 -0700 (PDT) Message-ID: Date: Fri, 14 Sep 2007 09:26:20 +0300 From: "Agris Ameriks" To: Agris.Ameriks@gmail.com, "=?ISO-8859-13?Q?J=E2nis_Erts?=" Subject: =?UTF-8?Q?15.septembr=C4=AB_neaizmirstams_pas=C4=81kums!?= MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="----=_Part_979_8743786.1189751181201" Return-Path: agris.ameriks@gmail.com X-OriginalArrivalTime: 14 Sep 2007 06:46:01.0247 (UTC) FILETIME=[E9DF4AF0:01C7F69A] ------=_Part_979_8743786.1189751181201 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: base64 Content-Disposition: inline TGFiZGllbiEKCkluZm9ybcSTamFtIErFq3MgcGFyIGdyYW5kaW96dSBzdHVkZW50dSBwYXPEgWt1 bXUgUsSrZ2FzIGNlbnRyxIEgLSBFc3BsYW7EgWTEkyEKCjE1LnNlcHRlbWJyxKsgUsSrZ8SBLCBF c3BsYW7EgWTEkywgbm90aWtzIG5lYWl6bWlyc3RhbXMgcGFzxIFrdW1zIGphdW5pZcWhaWVtCuKA kyBTdHVkZW50dSBQxIFydGlqcyEKClV6c3TEgXNpZXMgcG9wdWzEgXJhcyBncnVwYXMsIGvEgSBD UkVETywgTW9ybmluZyBBZnRlciwgTmV3T2xkLApTb3VuZEFyY2FkZSwgQ2Fjb3Bob25pY3MsIGvE gSBhcsSrIGltcHJvdml6xIFjaWphcyB0ZcSBdHJpcyBIYW1sZXRzIHVuIGLFq3MKaWVzcMSTamEg dsSTcm90LCBrxIEgZHppZXNtdSBkdWVsxKsgc2FjZW7FoWFzIHJla3RvcmkgdW4gc3R1ZGVudGku ClV6c3TEgXNpZXMgYXLEqyB2aWpvbG5pZWNlIENyaXNDYW50by4KClBhcmvEgSBub3Rpa3Mgc2Vt aW7EgXJzLCBrdXJhIGlldHZhcm9zIHZhcsSTcyBub2tsYXVzxKt0aWVzIGd1ZHJ1IGNpbHbEk2t1 Cmxla2NpamFzOiBwcm9mLiBBbmRyZWpzIEPEk2JlcnMsIHByb2YuIEl2YXJzIEzEgWNpcywgSnVy aXMgxaB0ZWluYmVyZ3MsCk9sZ2EgVsSrdG9sacWGYSwgSWxnb25pcyBWaWxrcyB1LmMuCgpNxJNy xLdpcyAtIG9yZ2FuaXrEk3QgcGFzxIFrdW11IHN0dWRlbnRpZW0sIGt1ciBqYXVuaWXFoWkgdmFy xJNzIGRhdWR6cHVzxKtnaQpwYXZhZMSrdCBsYWlrdSwgdHVya2zEgXQsIHBhciBicsSrdnUuIFN0 dWRlbnRpZW0gdGlrcyBwaWVkxIF2xIF0cyB2xJNyb3QKbXV6aWvEgWx1cyB1biB0ZWF0csSBbHVz IHByaWVrxaFuZXN1bXVzLCBwYXBpbGRpbsSBdCBzYXZhcyB6aW7EgcWhYW5hcwphcG1la2zEk2pv dCBkYcW+xIFkdXMgc2VtaW7EgXJ1cyB1biBsZWtjaWphcyBwYXIgemluxIF0bmksIHBpZWRhbMSr dGllcwpkYcW+xIFkxIFzIGFrdGl2aXTEgXTEk3MgdW4gc3DEk2zEk3MgKHN0YWZldGVzLCDFoWFo YSB0dXJuxKtycywgQUNDRU5UVVJFCnJvZGVvLCBSSU1JIGtsaW7FoWvEgXDEk2p1IHNpZW5hIHUu Yy4pLCBnxat0IHByYWt0aXNrYXMgaWVtYcWGYXMgc2Fsc2FzCm5vZGFyYsSrYsSBcywga8SBIGFy xKsgdsSTcm9qb3QgamF1bm9zIG3EgWtzbGluaWVrdXMgbm8gTE1BIHZpxYZ1IHJhZG/FoWFqxIEK ZGFyYsSBLCBrdXIgdmFyxJNzIGllc2Fpc3TEq3RpZXMgYXLEqyBza2F0xKt0xIFqaS4gU3R1ZGVu dGllbSBixatzIGl6ZGV2xKtiYQppZXBhesSrdGllcyB1biBpZXNhaXN0xKt0aWVzIG9yZ2FuaXrE gWNpasSBcy4gVmlzYSBwYXPEgWt1bWEgbGFpa8SBCmFwbWVrbMSTdMSBamllbSBixatzIGllc3DE k2phIHBhbMSrZHrEk3QgIk1hcnNhIGdhdHZlcyIga3LEq3plcyBjZW50cmFtIGFyCm5hdWRpxYZ1 LCBhcMSjxJNyYnUgdmFpIGVsZWt0cm9uaWt1LgoKVU4gVEFTIFZJU1MgQkVaIE1BS1NBUyEKCk5v c2zEk2d1bcSBIHBhc8SBa3VtYSBhcG1la2zEk3TEgWppIHZhcsSTcyBsYWltxJN0IG1vYmlsbyB0 ZWxlZm9udSBOT0tJQSA2MzAwCnVuIHBvcnRhdMSrdm8gZGF0b3J1IQoKVmllbsSBIHRlaWt1bcSB IHZhciB0ZWlrdCwga2Eg4oCeU3R1ZGVudHUgUMSAUlRJSlMhIiBpciBtdXppa8SBbGkgdW4KdGVh dHLEgWxpIGF0cmFrdMSrdmkgYWt0xKt2cyB1biBpbnRlbGVrdHXEgWxpIHVuIGluZm9ybWF0xKt2 aSBpemdsxKt0b2pvxaFzCmxhYmRhcsSrYmFzIHBhc8SBa3VtcyBqYXVuaWXFoWllbS4KClBhc8SB a3VtxIEgcGllZGFsxKtzaWVzIGFyxKsgxaHEgWRhcyBvcmdhbml6xIFjaWphczogU3R1ZGVudHUg a29vcnBvcsSBY2lqdQphcHZpZW7Eq2JhLCBCaWVkcsSrYmFzICJMYXR2aWphcyBNYXpwdWxraSIs IExhdHZpamFzIEtyaXN0xKtnxIEgU3R1ZGVudHUKYnLEgWzEq2JhLCBBZ2FwZSBMYXR2aWphIHUu Yy4KCkxpZWxzIHBhbGRpZXMgbcWrc3UgYXRiYWxzdMSrdMSBamllbTogUsSrZ2FzIERvbWVpLCBB Q0NFTlRVUkUsIFJJTUkuIEvEgQphcsSrIHBhbGRpZXMgZHJhdWdpZW0ubHYsIExUViwgRElFTkEs IDVtaW4sIEtvbnRpIEJ1c3MsIEFsZGFyaXMsIERvdWJsZQpDb2ZmZWUsIFByb1dlYiwgUsSrZ2Fz IFpvb2TEgXJ6cy4KClZhaXLEgWsgaW5mbyB3d3cuc3R1ZGVudHBhcnR5Lmx2LgoKMTQuMDkuMjAw NwoKCgpTYWdhdGF2b2phClNhbmRhIEJsb21rYWxuYQoKCi0tIApBciBjaWXFhnUsCkFncmlzIEFt ZXJpa3MKTW9iLnRlbC4gMiA2NDYxMTAxCkUtcGFzdHM6IEFncmlzLkFtZXJpa3NAZ21haWwuY29t Cg== ------=_Part_979_8743786.1189751181201 Content-Type: application/msword; name="PR_SP.doc" Content-Transfer-Encoding: base64 Content-Disposition: attachment; filename="PR_SP.doc" X-Attachment-Id: f_f6kb3mdz 0M8R4KGxGuEAAAAAAAAAAAAAAAAAAAAAPgADAP7/CQAGAAAAAAAAAAAAAAABAAAANAAAAAAAAAAA EAAANgAAAAEAAAD+////AAAAADMAAAD///////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////s pcEAW4AJBAAA8BK/AAAAAAAAEAAAAAAACAAAUhwAAA4AYmpiaqz6rPoAAAAAAAAAAAAAAAAAAAAA AAAJBBYALiIAAM6QAQDOkAEA6gcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD//w8AAAAA AAAAAAD//w8AAAAAAAAAAAD//w8AAAAAAAAAAAAAAAAAAAAAALcAAAAAAAAGAAAAAAAAAAYAAEMT AAAAAAAAQxMAAAAAAABDEwAAAAAAAEMTAAAAAAAAQxMAABQAAAAAAAAAAAAAAP////8AAAAAVxMA AAAAAABXEwAAAAAAAFcTAAAAAAAAVxMAABQAAABrEwAAFAAAAFcTAAAAAAAA9xwAAPgAAAB/EwAA FgAAAJUTAAAAAAAAlRMAAAAAAACVEwAAAAAAAJUTAAAAAAAAcBQAAB4AAACOFAAADAAAAJoUAAAI AAAAahwAAAIAAABsHAAAAAAAAGwcAAAAAAAAbBwAAAAAAABsHAAAAAAAAGwcAAAAAAAAbBwAACQA AADvHQAAogIAAJEgAAB2AAAAkBwAACEAAAAAAAAAAAAAAAAAAAAAAAAAQxMAAAAAAACiFAAAAAAA AAAAAAAAAAAAAAAAAAAAAABwFAAAAAAAAHAUAAAAAAAAohQAAAAAAACiFAAAAAAAAJAcAAAAAAAA AAAAAAAAAABDEwAAAAAAAEMTAAAAAAAAlRMAAAAAAAAAAAAAAAAAAJUTAADbAAAAsRwAABYAAACG GQAAAAAAAIYZAAAAAAAAhhkAAAAAAACiFAAAwgIAAEMTAAAAAAAAlRMAAAAAAABDEwAAAAAAAJUT AAAAAAAAahwAAAAAAAAAAAAAAAAAAIYZAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAohQAAAAAAABqHAAAAAAAAAAAAAAAAAAAhhkAAAAAAACGGQAA HgAAAK4bAAAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA1hsAAAAAAACVEwAAAAAAAP////8AAAAAsLTM6Zf2 xwEAAAAAAAAAAFcTAAAAAAAAZBcAAOgAAADGGwAACAAAAAAAAAAAAAAAVhwAABQAAADHHAAAMAAA APccAAAAAAAAzhsAAAgAAAAHIQAAAAAAAEwYAACaAAAAByEAABAAAADWGwAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADW GwAAFAAAAAchAAAAAAAAAAAAAAAAAABDEwAAAAAAAOobAABsAAAAohQAAAAAAACiFAAAAAAAAIYZ AAAAAAAAohQAAAAAAACiFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAohQA AAAAAACiFAAAAAAAAKIUAAAAAAAAkBwAAAAAAACQHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAA5hgAAKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKIUAAAA AAAAohQAAAAAAACiFAAAAAAAAPccAAAAAAAAohQAAAAAAACiFAAAAAAAAKIUAAAAAAAAohQAAAAA AAAAAAAAAAAAAP////8AAAAA/////wAAAAD/////AAAAAAAAAAAAAAAA/////wAAAAD/////AAAA AP////8AAAAA/////wAAAAD/////AAAAAP////8AAAAA/////wAAAAD/////AAAAAP////8AAAAA /////wAAAAD/////AAAAAP////8AAAAA/////wAAAAD/////AAAAAAchAAAAAAAAohQAAAAAAACi FAAAAAAAAKIUAAAAAAAAohQAAAAAAACiFAAAAAAAAKIUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACiFAAAAAAAAKIUAAAAAAAAohQA AAAAAAAABgAACQwAAAkSAAA6AQAABQASAQAACQQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFMAdAB1 AGQAZQBuAHQAdQAgAFAAAAFSAFQASQBKAFMADQAyADAAMAA3AC4AIABnAGEAZABhACAAMQA1AC4A cwBlAHAAdABlAG0AYgByACsBDQBFAHMAcABsAGEAbgABAWQAEwENAA0ADQAxADUALgBzAGUAcAB0 AGUAbQBiAHIAKwEgAFIAKwFnAAEBLAAgAEUAcwBwAGwAYQBuAAEBZAATASwAIABuAG8AdABpAGsA cwAgAG4AZQBhAGkAegBtAGkAcgBzAHQAYQBtAHMAIABwAGEAcwABAWsAdQBtAHMAIABqAGEAdQBu AGkAZQBhAWkAZQBtACAAEyAgAFMAdAB1AGQAZQBuAHQAdQAgAFAAAQFyAHQAaQBqAHMAIQANAA0A VQB6AHMAdAABAXMAaQBlAHMAIABwAG8AcAB1AGwAAQFyAGEAcwAgAGcAcgB1AHAAYQBzACwAIABr AAEBIABDAFIARQBEAE8ALAAgAE0AbwByAG4AaQBuAGcAIABBAGYAdABlAHIALAAgAE4AZQB3AE8A bABkACwAIABTAG8AdQBuAGQAQQByAGMAYQBkAGUALAAgAEMAYQBjAG8AcABoAG8AbgBpAGMAcwAs ACAAawABASAAYQByACsBIABpAG0AcAByAG8AdgBpAHoAAQFjAGkAagBhAHMAIAB0AGUAAQF0AHIA aQBzACAASABhAG0AbABlAHQAcwAgAHUAbgAgAGIAawFzACAAaQBlAHMAcAATAWoAYQAgAHYAEwFy AG8AdAAsACAAawABASAAZAB6AGkAZQBzAG0AdQAgAGQAdQBlAGwAKwEgAHMAYQBjAGUAbgBhAWEA cwAgAHIAZQBrAHQAbwByAGkAIAB1AG4AIABzAHQAdQBkAGUAbgB0AGkALgAgAFUAegBzAHQAAQFz AGkAZQBzACAAYQByACsBIAB2AGkAagBvAGwAbgBpAGUAYwBlACAAQwByAGkAcwBDAGEAbgB0AG8A LgANAA0AUABhAHIAawABASAAbgBvAHQAaQBrAHMAIABzAGUAbQBpAG4AAQFyAHMALAAgAGsAdQBy AGEAIABpAGUAdAB2AGEAcgBvAHMAIAB2AGEAcgATAXMAIABuAG8AawBsAGEAdQBzACsBdABpAGUA cwAgAGcAdQBkAHIAdQAgAGMAaQBsAHYAEwFrAHUAIABsAGUAawBjAGkAagBhAHMAOgAgAHAAcgBv AGYALgAgAEEAbgBkAHIAZQBqAHMAIABDABMBYgBlAHIAcwAsACAAcAByAG8AZgAuACAASQB2AGEA cgBzACAATAABAWMAaQBzACwAIABKAHUAcgBpAHMAIABgAXQAZQBpAG4AYgBlAHIAZwBzACwAIABP AGwAZwBhACAAVgArAXQAbwBsAGkARgFhACwAIABJAGwAZwBvAG4AaQBzACAAVgBpAGwAawBzACAA dQAuAGMALgANAA0ATQATAXIANwFpAHMAIAAtACAAbwByAGcAYQBuAGkAegATAXQAIABwAGEAcwAB AWsAdQBtAHUAIABzAHQAdQBkAGUAbgB0AGkAZQBtACwAIABrAHUAcgAgAGoAYQB1AG4AaQBlAGEB aQAgAHYAYQByABMBcwAgAGQAYQB1AGQAegBwAHUAcwArAWcAaQAgAHAAYQB2AGEAZAArAXQAIABs AGEAaQBrAHUALAAgAHQAdQByAGsAbAABAXQALAAgAHAAYQByACAAYgByACsBdgB1AC4AIABTAHQA dQBkAGUAbgB0AGkAZQBtACAAdABpAGsAcwAgAHAAaQBlAGQAAQF2AAEBdABzACAAdgATAXIAbwB0 ACAAbQB1AHoAaQBrAAEBbAB1AHMAIAB1AG4AIAB0AGUAYQB0AHIAAQFsAHUAcwAgAHAAcgBpAGUA awBhAW4AZQBzAHUAbQB1AHMALAAgAHAAYQBwAGkAbABkAGkAbgABAXQAIABzAGEAdgBhAHMAIAB6 AGkAbgABAWEBYQBuAGEAcwAgAGEAcABtAGUAawBsABMBagBvAHQAIABkAGEAfgEBAWQAdQBzACAA cwBlAG0AaQBuAAEBcgB1AHMAIAB1AG4AIABsAGUAawBjAGkAagBhAHMAIABwAGEAcgAgAHoAaQBu AAEBdABuAGkALAAgAHAAaQBlAGQAYQBsACsBdABpAGUAcwAgAGQAYQB+AQEBZAABAXMAIABhAGsA dABpAHYAaQB0AAEBdAATAXMAIAB1AG4AIABzAHAAEwFsABMBcwAgACgAcwB0AGEAZgBlAHQAZQBz ACwAIABhAWEAaABhACAAdAB1AHIAbgArAXIAcwAsACAAQQBDAEMARQBOAFQAVQBSAEUAIAByAG8A ZABlAG8ALAAgAFIASQBNAEkAIABrAGwAaQBuAGEBawABAXAAEwFqAHUAIABzAGkAZQBuAGEAIAB1 AC4AYwAuACkALAAgAGcAawF0ACAAcAByAGEAawB0AGkAcwBrAGEAcwAgAGkAZQBtAGEARgFhAHMA IABzAGEAbABzAGEAcwAgAG4AbwBkAGEAcgBiACsBYgABAXMAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAACAIAAAi CAAAaAgAAPwIAAAeCQAAIAkAAFYJAABgCQAAjAkAAJgJAACaCQAAtAkAALYJAADOCQAA0AkAAN4J AAAMCgAAGgoAAKIKAADWCgAA6goAAOwKAADuCgAA8AoAAJALAAC4CwAAvAsAAEgMAABKDAAAYA8A AIIPAAAAFAAAUBUAAEYWAABIFgAAShYAAHoWAACQFgAAohYAAMoWAAAKFwAAMhcAADQXAAA2FwAA WhcAAGwXAABuFwAAtBcAAPz4/PTs9Ojk3fTW3dbd5NLo1ujSztLoysW7xbuz9Oyx9Kn0pMWd5J30 7JnSlIyFewAAEhVopQq8ABZopQq8ADUIgV0IgQAMFmilCrwANQiBXQiBAA8VaKUKvAAWaKUKvABd CIEJFmilCrwAXQiBBhZoumi3AAAMFWhPOIMAFmhPOIMAAAkWaE84gwBcCIEPFWilCrwAFmjpbksA NQiBA1UIAQ8VaOluSwAWaOluSwBcCIESFWhPOIMAFmjpbksANQiBXAiBAAkWaOluSwBcCIEGFmjB FFAAAAYWaDwgEAAABhZopQq8AAAMFWilCrwAFmiuAm4AAAwVaKUKvAAWaE84gwAABhZoTziDAAAG FmiuAm4AAA8VaOluSwAWaOluSwA1CIEGFmjpbksAAAYWaPpPewAABhZoszapADAACAAAIggAAFII AABmCAAAaAgAAGoIAAAgCQAAIgkAAO4KAADwCgAASgwAAEwMAABIFgAAShYAAHoWAAB8FgAANBcA ADYXAAB+GAAAgBgAAMoZAADMGQAAIhsAACQbAAC8GwAAvhsAANQbAAD9AAAAAAAAAAAAAAAA/QAA AAAAAAAAAAAAAP0AAAAAAAAAAAAAAAD9AAAAAAAAAAAAAAAA/QAAAAAAAAAAAAAAAP0AAAAAAAAA AAAAAAD9AAAAAAAAAAAAAAAA9QAAAAAAAAAAAAAAAP0AAAAAAAAAAAAAAADtAAAAAAAAAAAAAAAA /QAAAAAAAAAAAAAAAO0AAAAAAAAAAAAAAAD9AAAAAAAAAAAAAAAA/QAAAAAAAAAAAAAAAP0AAAAA AAAAAAAAAAD1AAAAAAAAAAAAAAAA/QAAAAAAAAAAAAAAAPUAAAAAAAAAAAAAAAD1AAAAAAAAAAAA AAAA9QAAAAAAAAAAAAAAAP0AAAAAAAAAAAAAAAD9AAAAAAAAAAAAAAAA/QAAAAAAAAAAAAAAAP0A AAAAAAAAAAAAAAD9AAAAAAAAAAAAAAAA5QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHAAADJAJh JAJnZKUKvAAABwAAAyQDYSQDZ2TpbksAAAcAAAMkA2EkA2dkpQq8AAABAAAAGiwAIABrAAEBIABh AHIAKwEgAHYAEwFyAG8AagBvAHQAIABqAGEAdQBuAG8AcwAgAG0AAQFrAHMAbABpAG4AaQBlAGsA dQBzACAAbgBvACAATABNAEEAIAB2AGkARgF1ACAAcgBhAGQAbwBhAWEAagABASAAZABhAHIAYgAB ASwAIABrAHUAcgAgAHYAYQByABMBcwAgAGkAZQBzAGEAaQBzAHQAKwF0AGkAZQBzACAAYQByACsB IABzAGsAYQB0ACsBdAABAWoAaQAuACAAUwB0AHUAZABlAG4AdABpAGUAbQAgAGIAawFzACAAaQB6 AGQAZQB2ACsBYgBhACAAaQBlAHAAYQB6ACsBdABpAGUAcwAgAHUAbgAgAGkAZQBzAGEAaQBzAHQA KwF0AGkAZQBzACAAbwByAGcAYQBuAGkAegABAWMAaQBqAAEBcwAuACAAVgBpAHMAYQAgAHAAYQBz AAEBawB1AG0AYQAgAGwAYQBpAGsAAQEgAGEAcABtAGUAawBsABMBdAABAWoAaQBlAG0AIABiAGsB cwAgAGkAZQBzAHAAEwFqAGEAIABwAGEAbAArAWQAegATAXQAIAAiAE0AYQByAHMAYQAgAGcAYQB0 AHYAZQBzAB0gIABrAHIAKwF6AGUAcwAgAGMAZQBuAHQAcgBhAG0AIABhAHIAIABuAGEAdQBkAGkA RgF1ACwAIABhAHAAIwETAXIAYgB1ACAAdgBhAGkAIABlAGwAZQBrAHQAcgBvAG4AaQBrAHUALgAg AA0ADQBVAE4AIABUAEEAUwAgAFYASQBTAFMAIABCAEUAWgAgAE0AQQBLAFMAQQBTACEADQANAE4A bwBzAGwAEwFnAHUAbQABASAAcABhAHMAAQFrAHUAbQBhACAAYQBwAG0AZQBrAGwAEwF0AAEBagBp ACAAdgBhAHIAEwFzACAAbABhAGkAbQATAXQAIABtAG8AYgBpAGwAbwAgAHQAZQBsAGUAZgBvAG4A dQAgAE4ATwBLAEkAQQAgADYAMwAwADAAIAB1AG4AIABwAG8AcgB0AGEAdAArAXYAbwAgAGQAYQB0 AG8AcgB1ACEADQANAFYAaQBlAG4AAQEgAHQAZQBpAGsAdQBtAAEBIAB2AGEAcgAgAHQAZQBpAGsA dAAsACAAawBhACAAHiBTAHQAdQBkAGUAbgB0AHUAIABQAAABUgBUAEkASgBTACEAIgAgAGkAcgAg AG0AdQB6AGkAawABAWwAaQAgAHUAbgAgAHQAZQBhAHQAcgABAWwAaQAgAGEAdAByAGEAawB0ACsB dgBpACAAYQBrAHQAKwF2AHMAIAB1AG4AIABpAG4AdABlAGwAZQBrAHQAdQABAWwAaQAgAHUAbgAg AGkAbgBmAG8AcgBtAGEAdAArAXYAaQAgAGkAegBnAGwAKwF0AG8AagBvAGEBcwAgAGwAYQBiAGQA YQByACsBYgBhAHMAIABwAGEAcwABAWsAdQBtAHMAIABqAGEAdQBuAGkAZQBhAWkAZQBtAC4ADQAN AFAAYQBzAAEBawB1AG0AAQEgAHAAaQBlAGQAYQBsACsBcwBpAGUAcwAgAGEAcgArASAAYQEBAWQA YQBzACAAbwByAGcAYQBuAGkAegABAWMAaQBqAGEAcwA6ACAAUwB0AHUAZABlAG4AdAB1ACAAawBv AG8AcgBwAG8AcgABAWMAaQBqAHUAIABhAHAAdgBpAGUAbgArAWIAYQAsACAAQgBpAGUAZAByACsB YgBhAHMAIAAiAEwAYQB0AHYAaQBqAGEAcwAgAE0AYQB6AHAAdQBsAGsAaQAiACwAIABMAGEAdAB2 AGkAagBhAHMAIABLAHIAaQBzAHQAKwFnAAEBIABTAHQAdQBkAGUAbgB0AHUAIABiAHIAAQFsACsB YgBhACwAIABBAGcAYQBwAGUAIABMAGEAdAB2AGkAagBhACAAdQAuAGMALgANAA0ATABpAGUAbABz ACAAcABhAGwAZABpAGUAcwAgAG0AawFzAHUAIABhAHQAYgBhAGwAcwB0ACsBdAABAWoAaQBlAG0A OgAgAFIAKwFnAGEAcwAgAEQAbwBtAGUAaQAsACAAQQBDAEMARQBOAFQAVQBSAEUALAAgAFIASQBN AEkALgAgAEsAAQEgAGEAcgArASAAcABhAGwAZABpAGUAcwAgAGQAcgBhAHUAZwBpAGUAbQAuAGwA dgAsACAATABUAFYALAAgAEQASQBFAE4AQQAsACAANQBtAGkAbgAsACAASwBvAG4AdABpACAAQgB1 AHMAcwAsACAAQQBsAGQAYQByAGkAcwAsACAARABvAHUAYgBsAGUAIABDAG8AZgBmAGUAZQAsACAA UAByAG8AVwBlAGIALAAgAFIAKwFnAGEAcwAgAFoAbwBvAGQAAQFyAHoAcwAuAA0ADQBWAGEAaQBy AAEBawAgAGkAbgBmAG8AIAATACAASABZAFAARQBSAEwASQBOAEsAIAAiAGgAdAB0AHAAOgAvAC8A dwB3AHcALgBzAHQAdQBkAGUAbgB0AHAAYQByAHQAeQAuAGwAdgAiACAAFAB3AHcAdwAuAHMAdAB1 AGQAZQBuAHQAcABhAHIAdAB5AC4AbAB2ABUALgANAA0AMQA0AC4AMAA5AC4AMgAwADAANwANAA0A DQANAFMAYQBnAGEAdABhAHYAbwBqAGEADQBTAGEAbgBkAGEAIABCAGwAbwBtAGsAYQBsAG4AYQAN AA0AUgBlAGQAaQAjARMBagBhAA0AQQBnAHIAaQBzACAAQQBtAGUAcgBpAGsAcwANADIANgA0ADYA MQAxADAAMQANAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC0FwAAxBcAAAgYAAAMGAAA fBgAAH4YAACAGAAAHhkAAFgZAADIGQAAyhkAAMwZAAAgGwAAIhsAADwbAAA+GwAAjhsAAJAbAAC2 GwAAuBsAALwbAAC+GwAAwBsAAMIbAADSGwAA1BsAANobAADwGwAADhwAABAcAABSHAAA8ujy6OHa 1c3Vwbq2sq6moqaZpq6itpW2srayjrK2AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwVaKUKvAAWaKUKvAAABhZo 6W5LAAAQFWgGBf4AFmjvdpsAMEoQAAAGFmjvdpsAAA8DagAAAAAWaO92mwBVCAEGFmgDHEgAAAYW aLpotwAABhZopQq8AAAMFWhPOIMAFmilCrwAABcVaK938QAWaK938QBdCIFtSAUEc0gFBA8VaK93 8QAWaK938QBdCIEJFmivd/EAXQiBDBZor3fxADUIgV0IgQAMFmilCrwANQiBXQiBABIVaKUKvAAW aKUKvAA1CIFdCIEAGhVopQq8ABZopQq8ADUIgV0IgW1IBQRzSAUEHtQbAADWGwAA2BsAANobAADw GwAAEBwAABIcAAAkHAAAQBwAAFIcAAD9AAAAAAAAAAAAAAAA/QAAAAAAAAAAAAAAAP0AAAAAAAAA AAAAAAD9AAAAAAAAAAAAAAAA+AAAAAAAAAAAAAAAAPgAAAAAAAAAAAAAAAD4AAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAPgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAZ2SlCrwAAAEAAAAJLAAxkGgBH7CCLiCwxkEhsKUG IrBSAyOQbgQkkG4EJbAAABewxAIYsMQCDJDEAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABeBBEAEgABAAsBDwAHAAAAAAAA AAAABAAIAAAAmAAAAJ4AAACeAAAAngAAAJ4AAACeAAAAngAAAJ4AAACeAAAANgYAADYGAAA2BgAA NgYAADYGAAA2BgAANgYAADYGAAA2BgAAdgIAAHYCAAB2AgAAdgIAAHYCAAB2AgAAdgIAAHYCAAB2 AgAANgYAADYGAAA2BgAANgYAADYGAAA2BgAAPgIAADYGAAA2BgAANgYAADYGAAA2BgAANgYAADYG AAA2BgAANgYAADYGAAA2BgAANgYAADYGAAA2BgAANgYAADYGAAA2BgAANgYAADYGAAA2BgAANgYA ADYGAAA2BgAANgYAADYGAAA2BgAANgYAAKgAAAA2BgAANgYAABYAAAA2BgAANgYAADYGAAA2BgAA NgYAADYGAAA2BgAANgYAALgAAAA2BgAANgYAADYGAAA2BgAANgYAADYGAAA2BgAANgYAADYGAAA2 BgAANgYAADYGAABoAQAASAEAADYGAAA2BgAANgYAADYGAAA2BgAANgYAADYGAAA2BgAANgYAADYG AAA2BgAANgYAADYGAAA2BgAANgYAADYGAAA2BgAANgYAADYGAAA2BgAANgYAADYGAAA2BgAANgYA ADYGAAA2BgAANgYAADYGAAA2BgAANgYAADYGAAA2BgAANgYAADYGAAA2BgAANgYAADYGAAA2BgAA NgYAADYGAAA2BgAANgYAADYGAAA2BgAANgYAADYGAAA2BgAANgYAADYGAAA2BgAANgYAADYGAAA2 BgAANgYAADYGAAA2BgAANgYAADYGAAA2BgAANgYAADYGAAA2BgAANgYAADYGAAA2BgAAsAMAADYG AAAyBgAAGAAAAMADAADQAwAA4AMAAPADAAAABAAAEAQAACAEAAAwBAAAQAQAAFAEAABgBAAAcAQA AIAEAACQBAAAwAMAANADAADgAwAA8AMAAAAEAAAQBAAAMgYAACgCAADYAQAA6AEAACAEAAAwBAAA QAQAAFAEAABgBAAAcAQAAIAEAACQBAAAwAMAANADAADgAwAA8AMAAAAEAAAQBAAAIAQAADAEAABA BAAAUAQAAGAEAABwBAAAgAQAAJAEAADAAwAA0AMAAOADAADwAwAAAAQAABAEAAAgBAAAMAQAAEAE AABQBAAAYAQAAHAEAACABAAAkAQAAMADAADQAwAA4AMAAPADAAAABAAAEAQAACAEAAAwBAAAQAQA AFAEAABgBAAAcAQAAIAEAACQBAAAwAMAANADAADgAwAA8AMAAAAEAAAQBAAAIAQAADAEAABABAAA UAQAAGAEAABwBAAAgAQAAJAEAADAAwAA0AMAAOADAADwAwAAAAQAABAEAAAgBAAAMAQAAEAEAABQ BAAAYAQAAHAEAACABAAAkAQAADgBAABYAQAA+AEAAAgCAAAYAgAAVgIAAH4CAAAUAAAAX0gBBG1I CQRuSAkEc0gJBHRICQQAAAAAQAAAYPH/AgBAAAwQAAAAAAAAAAAGAE4AbwByAG0AYQBsAAAAAgAA ABgAQ0oYAF9IAQRhShgAbUgmBHNIJgR0SBkEAAAAAAAAAAAAAAAAAAAAAAAARABBYPL/oQBEAAwB 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 xnzSKn914qN74OgtuN+fMCVNMME3JYGh9RyYPIDktxzN0o2/AAAA//8DAFBLAwQUAAYACAAAACEA DdGQn7YAAAAbAQAAJwAAAHRoZW1lL3RoZW1lL19yZWxzL3RoZW1lTWFuYWdlci54bWwucmVsc4SP TQrCMBSE94J3CG9v07oQkSbdiNCt1AOE5DUNNj8kUeztDa4sCC6HYb6ZabuXnckTYzLeMWiqGgg6 6ZVxmsFtuOyOQFIWTonZO2SwYIKObzftFWeRSyhNJiRSKC4xmHIOJ0qTnNCKVPmArjijj1bkIqOm Qci70Ej3dX2g8ZsBfMUkvWIQe9UAGZZQmv+z/TgaiWcvHxZd/lFBc9mFBSiixszgI5uqTATKW7q6 xN8AAAD//wMAUEsBAi0AFAAGAAgAAAAhAIKKvBP6AAAAHAIAABMAAAAAAAAAAAAAAAAAAAAAAFtD b250ZW50X1R5cGVzXS54bWxQSwECLQAUAAYACAAAACEApdan58AAAAA2AQAACwAAAAAAAAAAAAAA AAArAQAAX3JlbHMvLnJlbHNQSwECLQAUAAYACAAAACEAa3mWFoMAAACKAAAAHAAAAAAAAAAAAAAA AAAUAgAAdGhlbWUvdGhlbWUvdGhlbWVNYW5hZ2VyLnhtbFBLAQItABQABgAIAAAAIQCWta3ilgYA AFAbAAAWAAAAAAAAAAAAAAAAANECAAB0aGVtZS90aGVtZS90aGVtZTEueG1sUEsBAi0AFAAGAAgA AAAhAA3RkJ+2AAAAGwEAACcAAAAAAAAAAAAAAAAAmwkAAHRoZW1lL3RoZW1lL19yZWxzL3RoZW1l TWFuYWdlci54bWwucmVsc1BLBQYAAAAABQAFAF0BAACWCgAAAAA8P3htbCB2ZXJzaW9uPSIxLjAi IGVuY29kaW5nPSJVVEYtOCIgc3RhbmRhbG9uZT0ieWVzIj8+DQo8YTpjbHJNYXAgeG1sbnM6YT0i aHR0cDovL3NjaGVtYXMub3BlbnhtbGZvcm1hdHMub3JnL2RyYXdpbmdtbC8yMDA2L21haW4iIGJn MT0ibHQxIiB0eDE9ImRrMSIgYmcyPSJsdDIiIHR4Mj0iZGsyIiBhY2NlbnQxPSJhY2NlbnQxIiBh Y2NlbnQyPSJhY2NlbnQyIiBhY2NlbnQzPSJhY2NlbnQzIiBhY2NlbnQ0PSJhY2NlbnQ0IiBhY2Nl bnQ1PSJhY2NlbnQ1IiBhY2NlbnQ2PSJhY2NlbnQ2IiBobGluaz0iaGxpbmsiIGZvbEhsaW5rPSJm b2xIbGluayIvPgAAAADqBwAADAAAIgAAAAD/////AAgAALQXAABSHAAACAAAAA8AAAAACAAA1BsA AFIcAAAJAAAAEAAAAF8HAACIBwAAnAcAAOoHAAATWBT/FYAPAADwOAAAAAAABvAYAAAAAggAAAIA AAABAAAAAQAAAAEAAAACAAAAQAAe8RAAAAD//wAAAAD/AICAgAD3AAAQAA8AAvCSAAAAEAAI8AgA AAABAAAAAQQAAA8AA/AwAAAADwAE8CgAAAABAAnwEAAAAAAAAAAAAAAAAAAAAAAAAAACAArwCAAA AAAEAAAFAAAADwAE8EIAAAASAArwCAAAAAEEAAAADgAAUwAL8B4AAAC/AQAAEADLAQAAAAD/AQAA CAAEAwkAAAA/AwEAAQAAABHwBAAAAAEAAAD//wEAAAALADAALgAxAF8AdABhAGIAbABlADEANgDl BAAA7AcAAAAAAADlBAAA7AcAAAAAAAA1AAAAQAAAAEIAAABFAAAASAAAAFAAAABTAAAAawAAAHEA AAB3AAAAfgAAAI8AAACRAAAAqwAAAK0AAACuAAAAsAAAAMwAAADOAAAA2QAAANsAAADmAAAA6AAA AOkAAADrAAAA7QAAAO8AAABRAQAAXQEAAF4BAABhAQAAawEAAGwBAAB1AQAAeAEAAMgBAADOAQAA 3AEAAOQBAAANAgAAEgIAACQCAAAtAgAAnAIAAKACAABqAwAAdAMAAJEDAACZAwAAnAMAAKgDAACw AwAAtwMAAMEDAADGAwAASwQAAE4EAABpBAAAbwQAAJwEAACiBAAArgQAALcEAADiBAAA5gQAAP0E AAAJBQAARQUAAEYFAABPBQAAUwUAAFoFAABiBQAAdwUAAHkFAACKBQAAjwUAAKMFAACkBQAAxwUA AMgFAAD5BQAAAQYAAAgGAAAKBgAADwYAABYGAAAYBgAAGgYAABsGAAAgBgAALQYAAC8GAABOBgAA UAYAAG0GAABvBgAAfwYAAIEGAACOBgAAkwYAAKUGAACtBgAAUQcAAFMHAABXBwAAWgcAAF8HAACg BwAAoQcAAK4HAAC5BwAAvwcAAMgHAADTBwAA6QcAAOwHAAAHAAUABwAFAAcABQAHAAUABwAFAAcA BQAHAAUABwAFAAcABQAHAAUABwAFAAcABQAHAAUABwAFAAcABQAHAAUABwAFAAcABQAHAAUABwAF AAcABQAHAAUABwAFAAcABQAHAAUABwAFAAcABQAHAAUABwAFAAcABQAHAAUABwAFAAcABQAHAAUA BwAFAAcABQAHAAUABwAFAAcABQAHAAUABwAFAAcABQAHAAUABwAFAAcABQAHAAUABwAFAAcABQAH AAUABwAFAAcABQAHAAUABwAFAAcABQAHAAUABwAFAAcABQAHAAUABwAAAAAAEAAAABEAAAAoAAAA KQAAADIAAAA1AAAAjwAAAJEAAAB2AQAAeAEAACQCAAAmAgAA5AQAAOYEAAD9BAAA/wQAAFoFAABc BQAA/wUAAAEGAAClBgAApwYAAFEHAABTBwAAngcAAKAHAACqBwAArgcAALgHAAC5BwAAyAcAAMoH AADSBwAA0wcAAOAHAADhBwAA6QcAAOwHAAAFAAcABQAHAAUABwAFAAcABQAHAAUABwAFAAcABQAH AAUABwAFAAcABQAHAAUABwAFAAcABQAHAAUABwAFAAcABQAHAAUABwAFAAcAAAAAADMAAACPAAAA kAAAAJAAAACrAAAAzAAAAM0AAADaAAAA2wAAAO8AAABRAQAAdgEAAHcBAAD9BAAABwUAAKYGAACn BgAAnwcAAKAHAACqBwAAqwcAAK4HAAC5BwAA6QcAAOwHAAADAAQAAwAEAAMABAADAAQAAwAEAAMA BAADAAQAAwAEAAMABAADAAQAAwAEAAMABAAHAAAAAAAzAAAAjwAAAJAAAACQAAAAxgAAAMwAAABr AQAAdQEAAHcBAAD9BAAARQUAAFoFAAD/BQAApQYAAF8HAACdBwAAnwcAAJ8HAAChBwAAogcAAK4H AACuBwAAyQcAAMkHAADpBwAA7AcAAAMABAADAAQAAwAEAAMABAADAAQAAwAEAAMABAADAAQAAwAE AAMABAADAAQAAwAEAAMABwABANkcA1Ue07rY/w//D/8P/w//D/8P/w//D/8PAAABAAAAAAABAAAA AAAAAAAAAAAAAAAAAAAAGAAAD4TQAhGEmP4VxgUAAdACBl6E0AJghJj+AgAAAC4AAQAAAAQAAQAA AAAAAAAAAAAAAAAAAAAAABgAAA+EoAURhJj+FcYFAAGgBQZehKAFYISY/gIAAQAuAAEAAAAAgAEA AAAAAAAAAAAAAAAAAAAAAAAYAAAPhHAIEYSY/hXGBQABcAgGXoRwCGCEmP4CAAIALgABAAAAAIAB AAAAAAAAAAAAAAAAAAAAAAAAGAAAD4RACxGEmP4VxgUAAUALBl6EQAtghJj+AgADAC4AAQAAAACA AQAAAAAAAAAAAAAAAAAAAAAAABgAAA+EEA4RhJj+FcYFAAEQDgZehBAOYISY/gIABAAuAAEAAAAA gAEAAAAAAAAAAAAAAAAAAAAAAAAYAAAPhOAQEYSY/hXGBQAB4BAGXoTgEGCEmP4CAAUALgABAAAA AIABAAAAAAAAAAAAAAAAAAAAAAAAGAAAD4SwExGEmP4VxgUAAbATBl6EsBNghJj+AgAGAC4AAQAA AACAAQAAAAAAAAAAAAAAAAAAAAAAABgAAA+EgBYRhJj+FcYFAAGAFgZehIAWYISY/gIABwAuAAEA AAAAgAEAAAAAAAAAAAAAAAAAAAAAAAAYAAAPhFAZEYSY/hXGBQABUBkGXoRQGWCEmP4CAAgALgAB AAAA2RwDVQAAAAAAAAAAAAAAAP///////wEAAAAAAP//AQAAAAAAAQAAfhdaAAAAAAAAAAAAAQIA AgAVAAAABAAAAAgAAADlAAAAAAAAABQAAAAVKQ4APCAQAAMcSADpbksAwRRQAK4CbgDpYnYA+k97 AE84gwC8G5AAWnSSAO92mwBzfaMAszapAD0stwC6aLcAsBG5AKUKvADQM+oAJmHsAK938QAAAAAA 6gcAAOwHAAAAAAAAAQAAAP9AAwABAAAAAADqBwAAABgTAwEAAQAAAAAAAQAAAAAAAAAAAAAAAhwA AAAAAAAAwQMAAOoHAABgAAAIAAAAAGAAABQAAAAA//8BAAAABwBVAG4AawBuAG8AdwBuAP//AQAI AAAAAAAAAAAAAAD//wEAAAAAAP//AAACAP//AAAAAP//AAACAP//AAAAAAQAAABHHpABAAACAgYD BQQFAgMEhyoAIAAAAIAIAAAAAAAAAP8BAAAAAAAAVABpAG0AZQBzACAATgBlAHcAIABSAG8AbQBh AG4AAAA1EJABAgAFBQECAQcGAgUHAAAAAAAAABAAAAAAAAAAAAAAAIAAAAAAUwB5AG0AYgBvAGwA AAAzLpABAAACCwYEAgICAgIEhyoAIAAAAIAIAAAAAAAAAP8BAAAAAAAAQQByAGkAYQBsAAAAQR6Q AQAAAgQFAwUEBgMCBO8CAKDrIABCAAAAAAAAAACfAAAAAAAAAEMAYQBtAGIAcgBpAGEAIABNAGEA dABoAAAAIgAEAPEIiBgA8MQCAABoAQAAAABUcrmmWHK5pgAAAAADAAgAAAAuAQAAvAYAAAEABAAA AAQAAxAOAAAALgEAALwGAAABAAQAAAAOAAAAAAAAACEDAPAQAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAKUGbgS0ALQAgYFyNAAAEAAZAGQAAAAZAAAA5gcAAOYHAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAADKD UQDwEAAIAP/9AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAhIUAAAAAAJ8P8PAQgBPwAA4wQAAP// /3////9/////f////3////9/////f////3+wEbkAAAQAADIAAAAAAAAAAAAAAAAAAAAAAAAAAAAh BAAAAAAAAAAAAAAAAAAAAAAAABAcAAADAAAAAAAAAAAAeAAAAHgAAAAAAAAAAAAAAKAFAAD//xIA AAAAAAAAEABTAHQAdQBkAGUAbgB0AHUAIABQAAABUgBUAEkASgBTAAAAAAAAAA8AUwBhAG4AZABh ACAAQgBsAG8AbQBrAGEAbABuAGEABwBBAG0AZQByAGkAawBzAAAAAAAAAAAAAAAAAAAAAAAAAAAA EAAAAAYAAAABAAAAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAA/v8AAAUBAgAAAAAAAAAAAAAAAAAAAAAAAQAAAOCFn/L5T2gQ q5EIACsns9kwAAAAhAEAABEAAAABAAAAkAAAAAIAAACYAAAAAwAAALQAAAAEAAAAwAAAAAUAAADY AAAABgAAAOQAAAAHAAAA8AAAAAgAAAAEAQAACQAAABQBAAASAAAAIAEAAAoAAABAAQAADAAAAEwB AAANAAAAWAEAAA4AAABkAQAADwAAAGwBAAAQAAAAdAEAABMAAAB8AQAAAgAAAOn9AAAeAAAAFAAA AFN0dWRlbnR1IFDEgFJUSUpTAAAAHgAAAAQAAAAAAAAAHgAAABAAAABTYW5kYSBCbG9ta2FsbmEA HgAAAAQAAAAAAAAAHgAAAAQAAAAAAAAAHgAAAAwAAABOb3JtYWwuZG90bQAeAAAACAAAAEFtZXJp a3MAHgAAAAQAAAAzAAAAHgAAABgAAABNaWNyb3NvZnQgT2ZmaWNlIFdvcmQAAABAAAAAADAaHgEA AABAAAAAAOhLR5f2xwFAAAAAAABZ1pf2xwEDAAAAAQAAAAMAAAAuAQAAAwAAALwGAAADAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAP7/AAAFAQIAAAAAAAAAAAAAAAAAAAAAAAIAAAAC1c3VnC4bEJOXCAArLPmu RAAAAAXVzdWcLhsQk5cIACss+a5AAQAA/AAAAAwAAAABAAAAaAAAAA8AAABwAAAABQAAAIAAAAAG AAAAiAAAABEAAACQAAAAFwAAAJgAAAALAAAAoAAAABAAAACoAAAAEwAAALAAAAAWAAAAuAAAAA0A AADAAAAADAAAAN4AAAACAAAA6f0AAB4AAAAIAAAAbWFqYXMAAAADAAAADgAAAAMAAAAEAAAAAwAA AOYHAAADAAAAAAAMAAsAAAAAAAAACwAAAAAAAAALAAAAAAAAAAsAAAAAAAAAHhAAAAEAAAASAAAA U3R1ZGVudHUgUMSAUlRJSlMADBAAAAIAAAAeAAAABgAAAFRpdGxlAAMAAAABAAAAuAAAAAMAAAAA AAAAIAAAAAEAAAA4AAAAAgAAAEAAAAABAAAAAgAAAAwAAABfUElEX0hMSU5LUwACAAAA6f0AAEEA AABwAAAABgAAAAMAAAA5AHEAAwAAAAAAAAADAAAAAAAAAAMAAAAFAAAAHwAAABwAAABoAHQAdABw ADoALwAvAHcAdwB3AC4AcwB0AHUAZABlAG4AdABwAGEAcgB0AHkALgBsAHYALwAAAB8AAAABAAAA AAB5AgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAABAAAAAgAAAAMAAAAEAAAABQAAAAYAAAAHAAAACAAAAAkAAAAKAAAACwAAAAwAAAANAAAA DgAAAA8AAAAQAAAAEQAAAP7///8TAAAAFAAAABUAAAAWAAAAFwAAABgAAAAZAAAAGgAAABsAAAAc AAAAHQAAAB4AAAAfAAAAIAAAACEAAAAiAAAA/v///yQAAAAlAAAAJgAAACcAAAAoAAAAKQAAACoA AAD+////LAAAAC0AAAAuAAAALwAAADAAAAAxAAAAMgAAAP7////9////NQAAAP7////+/////v// //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// /////1IAbwBvAHQAIABFAG4AdAByAHkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAWAAUB//////////8DAAAABgkCAAAAAADAAAAAAAAARgAAAAAAAAAAAAAAAJCy 6emX9scBNwAAAIAAAAAAAAAAMQBUAGEAYgBsAGUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4AAgH/////BQAAAP////8AAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAASAAAAFyEAAAAAAABXAG8AcgBkAEQAbwBjAHUAbQBlAG4AdAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGgACAQEAAAD//////////wAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAuIgAAAAAAAAUAUwB1AG0AbQBh AHIAeQBJAG4AZgBvAHIAbQBhAHQAaQBvAG4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAoAAIB AgAAAAQAAAD/////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIwAAAAAQAAAA AAAABQBEAG8AYwB1AG0AZQBuAHQAUwB1AG0AbQBhAHIAeQBJAG4AZgBvAHIAbQBhAHQAaQBvAG4A AAAAAAAAAAAAADgAAgH///////////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAArAAAAABAAAAAAAAABAEMAbwBtAHAATwBiAGoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEgACAP///////////////wAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB5AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////////////////AAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/ //////////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAABAAAA/v////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// /wEA/v8DCgAA/////wYJAgAAAAAAwAAAAAAAAEYnAAAATWljcm9zb2Z0IE9mZmljZSBXb3JkIDk3 LTIwMDMgRG9jdW1lbnQACgAAAE1TV29yZERvYwAQAAAAV29yZC5Eb2N1bWVudC44APQ5snEAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA ------=_Part_979_8743786.1189751181201-- --9B095B5ADSN=_01C7DED0EB082C7600015D0ALVAEI?EXCH.lvaei-- schleuder-3.6.0/spec/fixtures/mails/bounces/tt_bounce_14.txt.eml000066400000000000000000001256261401002544500246560ustar00rootroot00000000000000Delivered-To: agris.ameriks@gmail.com Received: by 10.67.102.1 with SMTP id e1cs84361ugm; Wed, 12 Sep 2007 22:26:04 -0700 (PDT) Received: by 10.66.249.8 with SMTP id w8mr2616245ugh.1189661164236; Wed, 12 Sep 2007 22:26:04 -0700 (PDT) Return-Path: <> Received: from regsers.diena.lv (regsers.diena.lv [159.148.131.3]) by mx.google.com with SMTP id m1si170995ugc.2007.09.12.22.25.57; Wed, 12 Sep 2007 22:26:04 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of regsers.diena.lv designates 159.148.131.3 as permitted sender) client-ip=159.148.131.3; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of regsers.diena.lv designates 159.148.131.3 as permitted sender) smtp.mail= Message-Id: <46e8c9e6.0172420a.5581.12b7SMTPIN_ADDED@mx.google.com> Received: (qmail 14150 invoked for bounce); 13 Sep 2007 11:30:06 +0300 Date: 13 Sep 2007 11:30:06 +0300 From: postmaster@regsers.diena.lv To: agris.ameriks@gmail.com Subject: failure notice Hi. This is the qmail-send program at regsers.diena.lv. I'm afraid I wasn't able to deliver your message to the following addresses. This is a permanent error; I've given up. Sorry it didn't work out. : Message rejected. Not enough storage space in user's mailbox to accept message. --- Below this line is a copy of the message. Return-Path: Received: (qmail 14146 invoked by uid 89); 13 Sep 2007 11:30:06 +0300 Delivered-To: ogreszinas.lv-irina.vavere@ogreszinas.lv Received: (qmail 14141 invoked by uid 89); 13 Sep 2007 11:30:06 +0300 Delivered-To: ogreszinas.lv-info@ogreszinas.lv Received: (qmail 14139 invoked from network); 13 Sep 2007 11:30:06 +0300 Received: from unknown (HELO mesers.diena.lv) (159.148.85.166) by regsers.diena.lv with SMTP; 13 Sep 2007 11:30:06 +0300 Received: from hu-out-0506.google.com (hu-out-0506.google.com [72.14.214.238]) by mesers.diena.lv (Postfix) with ESMTP id 64DFB25651 for ; Thu, 13 Sep 2007 08:25:43 +0300 (EEST) Received: by hu-out-0506.google.com with SMTP id 16so146768hue for ; Wed, 12 Sep 2007 22:25:44 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=beta; h=domainkey-signature:received:received:message-id:date:from:to:subject:cc:mime-version:content-type; bh=L2SyivlqHxtTjH5g4+fQw5fs6kGsOHDdZAIpOVCV8D8=; b=RM2JXrCYFBhkLe4yd6MxT0vmzvsHsyA32ylCdGEs6dezOLBcyT3lgh/t+qJ6XgJpJyDA6z2lEt3GRh8UvPhjD4Kl/Y6IuiNcuzZWVAXZ7MGTBiv+3wSBCU+pyQsQDGkZWLkBTX6MgAthHhOzZAhXnyfM1Oe1Dgg0Q2UCaz9bXY4= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=beta; h=received:message-id:date:from:to:subject:cc:mime-version:content-type; b=FRTW/6SXI8LlxwFqs1q82QJK0pNGrTWJ1KVsKIqnA++p++EGtHGryiAagnHG4s91WGGZ8IeRnQhiEPDqyG3GHqpYZR3GzmsluDdLGsKhi75yYfwXq8p+XAQ9AGGMFwYpq2RCrumuHNWWnAPLFvkIQePM/4aLKJ9Ms/ORwiinMXY= Received: by 10.67.26.7 with SMTP id d7mr2639740ugj.1189661104603; Wed, 12 Sep 2007 22:25:04 -0700 (PDT) Received: by 10.67.102.1 with HTTP; Wed, 12 Sep 2007 22:25:04 -0700 (PDT) Message-ID: Date: Thu, 13 Sep 2007 08:25:04 +0300 From: "Agris Ameriks" To: Agris.Ameriks@gmail.com Subject: =?ISO-8859-13?Q?15.septembr=EE_Studentu_P=E2rtijs!?= Cc: "=?ISO-8859-13?Q?J=E2nis_Erts?=" , "Edgars Gutkis" , "Toms Beinerts" MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="----=_Part_8802_28973416.1189661104602" X-asdiena.lv-MailScanner: Found to be clean X-asdiena.lv-MailScanner-SpamCheck: not spam, SpamAssassin (score=0, required 5.4) X-asdiena.lv-MailScanner-From: agris.ameriks@gmail.com ------=_Part_8802_28973416.1189661104602 Content-Type: text/plain; charset=ISO-8859-13 Content-Transfer-Encoding: base64 Content-Disposition: inline TGFiZGllbiEKCjE1LnNlcHRlbWJy7iBFc3BsYW7iZOcgbm90aWtzIFN0dWRlbnR1IFDCUlRJSlMh CgpOb3P7dHUgSnVtcyByZWzuemkuCgotLSAKQXIgY2ll8nUsCkFncmlzIEFtZXJpa3MKTW9iLnRl bC4gMiA2NDYxMTAxCkUtcGFzdHM6IEFncmlzLkFtZXJpa3NAZ21haWwuY29tCg== ------=_Part_8802_28973416.1189661104602 Content-Type: application/msword; name="Studentu_Partijs_relize.doc" Content-Transfer-Encoding: base64 Content-Disposition: attachment; filename="Studentu_Partijs_relize.doc" X-Attachment-Id: f_f6ith33e 0M8R4KGxGuEAAAAAAAAAAAAAAAAAAAAAPgADAP7/CQAGAAAAAAAAAAAAAAABAAAANAAAAAAAAAAA EAAANgAAAAEAAAD+////AAAAADMAAAD///////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////s pcEAW4AJBAAA8BK/AAAAAAAAEAAAAAAACAAAlhwAAA4AYmpiaqz6rPoAAAAAAAAAAAAAAAAAAAAA AAAJBBYALiIAAM6QAQDOkAEAGQgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD//w8AAAAA AAAAAAD//w8AAAAAAAAAAAD//w8AAAAAAAAAAAAAAAAAAAAAALcAAAAAAAAGAAAAAAAAAAYAAEMT AAAAAAAAQxMAAAAAAABDEwAAAAAAAEMTAAAAAAAAQxMAABQAAAAAAAAAAAAAAP////8AAAAAVxMA AAAAAABXEwAAAAAAAFcTAAAAAAAAVxMAABQAAABrEwAAFAAAAFcTAAAAAAAAKRwAAPgAAAB/EwAA FgAAAJUTAAAAAAAAlRMAAAAAAACVEwAAAAAAAJUTAAAAAAAAcBQAAB4AAACOFAAADAAAAJoUAAAI AAAAwBsAAAIAAADCGwAAAAAAAMIbAAAAAAAAwhsAAAAAAADCGwAAAAAAAMIbAAAAAAAAwhsAAAAA AAAhHQAAogIAAMMfAABuAAAAwhsAACEAAAAAAAAAAAAAAAAAAAAAAAAAQxMAAAAAAACiFAAAAAAA AAAAAAAAAAAAAAAAAAAAAABwFAAAAAAAAHAUAAAAAAAAohQAAAAAAACiFAAAAAAAAMIbAAAAAAAA AAAAAAAAAABDEwAAAAAAAEMTAAAAAAAAlRMAAAAAAAAAAAAAAAAAAJUTAADbAAAA4xsAABYAAADk GAAAAAAAAOQYAAAAAAAA5BgAAAAAAACiFAAAngIAAEMTAAAAAAAAlRMAAAAAAABDEwAAAAAAAJUT AAAAAAAAwBsAAAAAAAAAAAAAAAAAAOQYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAohQAAAAAAADAGwAAAAAAAAAAAAAAAAAA5BgAAAAAAADkGAAA HgAAAAwbAAAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANBsAAAAAAACVEwAAAAAAAP////8AAAAA8CKPS8b1 xwEAAAAAAAAAAFcTAAAAAAAAQBcAANYAAAAkGwAACAAAAAAAAAAAAAAArBsAABQAAAD5GwAAMAAA ACkcAAAAAAAALBsAAAgAAAAxIAAAAAAAABYYAACOAAAAMSAAABAAAAA0GwAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0 GwAAFAAAADEgAAAAAAAAAAAAAAAAAABDEwAAAAAAAEgbAABkAAAAohQAAAAAAACiFAAAAAAAAOQY AAAAAAAAohQAAAAAAACiFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAohQA AAAAAACiFAAAAAAAAKIUAAAAAAAAwhsAAAAAAADCGwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAApBgAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKIUAAAA AAAAohQAAAAAAACiFAAAAAAAACkcAAAAAAAAohQAAAAAAACiFAAAAAAAAKIUAAAAAAAAohQAAAAA AAAAAAAAAAAAAP////8AAAAA/////wAAAAD/////AAAAAAAAAAAAAAAA/////wAAAAD/////AAAA AP////8AAAAA/////wAAAAD/////AAAAAP////8AAAAA/////wAAAAD/////AAAAAP////8AAAAA /////wAAAAD/////AAAAAP////8AAAAA/////wAAAAD/////AAAAADEgAAAAAAAAohQAAAAAAACi FAAAAAAAAKIUAAAAAAAAohQAAAAAAACiFAAAAAAAAKIUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACiFAAAAAAAAKIUAAAAAAAAohQA AAAAAAAABgAACQwAAAkSAAA6AQAABQASAQAACQQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFMAdAB1 AGQAZQBuAHQAdQAgAFAAAAFSAFQASQBKAFMADQAyADAAMAA3AC4AIABnAGEAZABhACAAMQA1AC4A cwBlAHAAdABlAG0AYgByACsBDQBFAHMAcABsAGEAbgABAWQAEwENAA0AMQA1AC4AIABzAGUAcAB0 AGUAbQBiAHIAKwEgAFIAKwFnAAEBLAAgAEUAcwBwAGwAYQBuAAEBZAATASwAIABKAGEAdQBuAGkA ZQBhAXUAIABtABMBbgBlAGEBYQAgAGkAZQB0AHYAYQByAG8AcwAgAG4AbwB0AGkAZQBrACAAcABh AHMAAQFrAHUAbQBzACAAagBhAHUAbgBpAGUAYQFpAGUAbQAgAC0AIABTAHQAdQBkAGUAbgB0AHUA IABQAAABUgBUAEkASgBTAC4AIAAgAFAAcgBvAGoAZQBrAHQAdQAgAG8AcgBnAGEAbgBpAHoAEwEg AEwAYQB0AHYAaQBqAGEAcwAgAFUAbgBpAHYAZQByAHMAaQB0AAEBdABlAHMAIABGAGkAegBpAGsA YQBzACAAdQBuACAAbQBhAHQAZQBtAAEBdABpAGsAYQBzACAAZgBhAGsAdQBsAHQAAQF0AGUAcwAg AEYAaQB6AG0AYQB0AHUAIABhAHQAYgBhAGwAcwB0AGEAIABmAG8AbgBkAHMAIABzAGEAZABhAHIA YgArAWIAAQEgAGEAcgAgAEwAYQB0AHYAaQBqAGEAcwAgAE0AAQFrAHMAbABhAHMAIABhAGsAYQBk ABMBbQBpAGoAYQBzACwAIABMAGEAdAB2AGkAagBhAHMAIABLAHUAbAB0AGsBcgBhAHMAIABhAGsA YQBkABMBbQBpAGoAYQBzACAAdQBuACAASgABAXoAZQBwAGEAIABWACsBdABvAGwAYQAgAEwAYQB0 AHYAaQBqAGEAcwAgAE0AawF6AGkAawBhAHMAIABhAGsAYQBkABMBbQBpAGoAYQBzACAAUwB0AHUA ZABlAG4AdAB1ACAAcABhAGEBcAABAXIAdgBhAGwAZAATAW0ALgANAA0ATQATAXIANwFpAHMAIAAt ACAAbwByAGcAYQBuAGkAegATAXQAIABwAGEAcwABAWsAdQBtAHUAIABzAHQAdQBkAGUAbgB0AGkA ZQBtACwAIABrAHUAcgAgAGoAYQB1AG4AaQBlAGEBaQAgAHYAYQByABMBcwAgAGQAYQB1AGQAegBw AHUAcwArAWcAaQAgAHAAYQB2AGEAZAArAXQAIABsAGEAaQBrAHUALAAgAHQAdQByAGsAbAABAXQA LAAgAHAAYQByACAAYgByACsBdgB1AC4AIABTAHQAdQBkAGUAbgB0AGkAZQBtACAAdABpAGsAcwAg AHAAaQBlAGQAAQF2AAEBdABzACAAdgATAXIAbwB0ACAAbQB1AHoAaQBrAAEBbAB1AHMAIAB1AG4A IAB0AGUAYQB0AHIAAQFsAHUAcwAgAHAAcgBpAGUAawBhAW4AZQBzAHUAbQB1AHMALAAgAHAAYQBw AGkAbABkAGkAbgABAXQAIABzAGEAdgBhAHMAIAB6AGkAbgABAWEBYQBuAGEAcwAgAGEAcABtAGUA awBsABMBagBvAHQAIABkAGEAfgEBAWQAdQBzACAAcwBlAG0AaQBuAAEBcgB1AHMAIAB1AG4AIABs AGUAawBjAGkAagBhAHMAIABwAGEAcgAgAHoAaQBuAAEBdABuAGkALAAgAHAAaQBlAGQAYQBsACsB dABpAGUAcwAgAGQAYQB+AQEBZAABAXMAIABhAGsAdABpAHYAaQB0AAEBdAATAXMAIAB1AG4AIABz AHAAEwFsABMBcwAgACgAcwB0AGEAZgBlAHQAZQBzACwAIABhAWEAaABhACAAdAB1AHIAbgArAXIA cwAsACAAQQBDAEMARQBOAFQAVQBSAEUAIAByAG8AZABlAG8ALAAgAFIASQBNAEkAIABrAGwAaQBu AGEBawABAXAAEwFqAHUAIABzAGkAZQBuAGEAIAB1AC4AYwAuACkALAAgAGcAawF0ACAAcAByAGEA awB0AGkAcwBrAGEAcwAgAGkAZQBtAGEARgFhAHMAIABzAGEAbABzAGEAcwAgAG4AbwBkAGEAcgBi ACsBYgABAXMALAAgAGsAAQEgAGEAcgArASAAdgATAXIAbwBqAG8AdAAgAGoAYQB1AG4AbwBzACAA bQABAWsAcwBsAGkAbgBpAGUAawB1AHMAIABuAG8AIABMAE0AQQAgAHYAaQBGAXUAIAByAGEAZABv AGEBYQBqAAEBIABkAGEAcgBiAAEBLAAgAGsAdQByACAAdgBhAHIAEwFzACAAaQBlAHMAYQBpAHMA dAArAXQAaQBlAHMAIABhAHIAKwEgAHMAawBhAHQAKwF0AAEBagBpAC4AIABTAHQAdQBkAGUAbgB0 AGkAZQBtACAAYgBrAXMAIABpAHoAZABlAHYAKwFiAGEAIABpAGUAcABhAHoAKwF0AGkAZQBzACAA dQBuACAAaQBlAHMAYQBpAHMAdAArAXQAaQBlAHMAIABvAHIAZwBhAG4AaQB6AAEBYwBpAGoAAQFz AC4AIABWAGkAcwBhACAAcABhAHMAAQFrAHUAbQBhACAAbABhAGkAawABASAAYQBwAG0AZQBrAGwA EwF0AAEBagBpAGUAbQAgAGIAawFzACAAaQBlAHMAcAATAWoAYQAgAHAAYQBsACsBZAB6ABMBdAAg ACIATQBhAHIAcwBhACAAZwBhAHQAdgBlAHMAHSAgAGsAcgArAXoAZQBzACAAYwBlAG4AdAByAGEA bQAgAGEAcgAgAG4AYQB1AGQAaQBGAXUALAAgAGEAcAAjARMBcgBiAHUAIAB2AGEAaQAgAGUAbABl AGsAdAByAG8AbgBpAGsAdQAuACAADQANAFUAegBzAHQAAQFzAGkAZQBzACAAcABvAHAAdQBsAAEB cgBhAHMAIABnAHIAdQBwAGEAcwAsACAAawABASAAQwBSAEUARABPACwAIABNAG8AcgBuAGkAbgBn ACAAQQBmAHQAZQByACwAIABWAG8AaQBjAGUAawBzACAAVgBvAGkAcwBrAGEALAAgAFMAbwB1AG4A ZABBAHIAYwBhAGQAZQAsACAAQwBhAGMAbwBwAGgAbwBuAGkAYwBzACwAIABrAAEBIABhAHIAKwEg AGkAbQBwAHIAbwB2AGkAegABAWMAaQBqAGEAcwAgAHQAZQABAXQAcgBpAHMAIABIAGEAbQBsAGUA dABzAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAIAgAACII AABoCAAADAkAAA4JAAASCQAAMgkAADYJAABcCQAAEAsAABILAAAUCwAAnA0AAOoNAABeDwAAZA8A AJoPAAAMEAAAJBAAACYQAACMEAAAkBAAAJIQAADIEAAA0hAAABoRAAAcEQAANhEAADgRAABQEQAA UhEAAGARAACOEQAAnBEAAAAWAACIFgAAvBYAANAWAADSFgAA1BYAANYWAAB2FwAAnhcAAKIXAAAu GAAAMBgAADIYAABIGAAAWhgAAMIYAADEGAAAxhgAAPz4/PTw9Ojj9N/839vX29Pby8PLw8vf29O8 tby1vNPw27Wz2/Cv8NurppymnJSmjdONifAAAAAAAAAAAAAABhZoumi3AAAMFWhPOIMAFmhPOIMA AA8VaE84gwAWaE84gwBcCIESFWhPOIMAFmhPOIMANQiBXAiBAAkWaE84gwBcCIEGFmjBFFAAAAYW aDwgEAAAA1UIAQwVaKUKvAAWaK4CbgAADBVopQq8ABZoTziDAAAPFWilCrwAFmhPOIMANQiBDxVo pQq8ABZorgJuADUIgQYWaE84gwAABhZoFSkOAAAGFmiuAm4AAAYWaD0stwAACRZorgJuADUIgQ8V aOlidgAWaOlidgA1CIEGFmilCrwAAAYWaOlidgAABhZo+k97AAAGFmizNqkANAAIAAAiCAAAUggA AGYIAABoCAAAEgsAABQLAACSEAAAlBAAANQWAADWFgAAMBgAADIYAAA0GAAAxBgAAMYYAAAOGgAA EBoAAGYbAABoGwAAABwAAAIcAAAYHAAAGhwAABwcAAAeHAAANBwAAFQcAAD9AAAAAAAAAAAAAAAA /QAAAAAAAAAAAAAAAP0AAAAAAAAAAAAAAAD9AAAAAAAAAAAAAAAA9QAAAAAAAAAAAAAAAP0AAAAA AAAAAAAAAAD1AAAAAAAAAAAAAAAA/QAAAAAAAAAAAAAAAPUAAAAAAAAAAAAAAAD9AAAAAAAAAAAA AAAA9QAAAAAAAAAAAAAAAP0AAAAAAAAAAAAAAAD9AAAAAAAAAAAAAAAA9QAAAAAAAAAAAAAAAP0A AAAAAAAAAAAAAAD1AAAAAAAAAAAAAAAA/QAAAAAAAAAAAAAAAP0AAAAAAAAAAAAAAAD9AAAAAAAA AAAAAAAA/QAAAAAAAAAAAAAAAP0AAAAAAAAAAAAAAADtAAAAAAAAAAAAAAAA/QAAAAAAAAAAAAAA AP0AAAAAAAAAAAAAAAD9AAAAAAAAAAAAAAAA/QAAAAAAAAAAAAAAAOgAAAAAAAAAAAAAAAAAAAQA AGdkpQq8AAAHAAADJAJhJAJnZKUKvAAABwAAAyQDYSQDZ2SlCrwAAAEAAAAbIAB1AG4AIABiAGsB cwAgAGkAZQBzAHAAEwFqAGEAIAB2ABMBcgBvAHQALAAgAGsAAQEgAGQAegBpAGUAcwBtAHUAIABk AHUAZQBsACsBIABzAGEAYwBlAG4AYQFhAHMAIAByAGUAawB0AG8AcgBpACAAdQBuACAAcwB0AHUA ZABlAG4AdABpAC4AIABVAHoAcwB0AAEBcwBpAGUAcwAgAGEAcgArASAAdgBpAGoAbwBsAG4AaQBl AGMAZQAgAEMAcgBpAHMAQwBhAG4AdABvAC4ADQANAFAAYQByAGsAAQEgAG4AbwB0AGkAawBzACAA cwBlAG0AaQBuAAEBcgBzACwAIABrAHUAcgBhACAAaQBlAHQAdgBhAHIAbwBzACAAdgBhAHIAEwFz ACAAbgBvAGsAbABhAHUAcwArAXQAaQBlAHMAIABnAHUAZAByAHUAIABjAGkAbAB2ABMBawB1ACAA bABlAGsAYwBpAGoAYQBzADoAIABwAHIAbwBmAC4AIABBAG4AZAByAGUAagBzACAAQwATAWIAZQBy AHMALAAgAHAAcgBvAGYALgAgAEkAdgBhAHIAcwAgAEwAAQFjAGkAcwAsACAASgB1AHIAaQBzACAA YAF0AGUAaQBuAGIAZQByAGcAcwAsACAATwBsAGcAYQAgAFYAKwF0AG8AbABpAEYBYQAsACAASQBs AGcAbwBuAGkAcwAgAFYAaQBsAGsAcwAgAHUALgBjAC4ADQANAA0ATgBvAHMAbAATAWcAdQBtAAEB IABwAGEAcwABAWsAdQBtAGEAIABhAHAAbQBlAGsAbAATAXQAAQFqAGkAIAB2AGEAcgATAXMAIABs AGEAaQBtABMBdAAgAG0AbwBiAGkAbABvACAAdABlAGwAZQBmAG8AbgB1ACAATgBPAEsASQBBACAA NgAzADAAMAAhAA0ADQBWAGkAZQBuAAEBIAB0AGUAaQBrAHUAbQABASAAdgBhAHIAIAB0AGUAaQBr AHQALAAgAGsAYQAgAB4gUwB0AHUAZABlAG4AdAB1ACAAUAAAAVIAVABJAEoAUwAhACIAIABpAHIA IABtAHUAegBpAGsAAQFsAGkAIAB1AG4AIAB0AGUAYQB0AHIAAQFsAGkAIABhAHQAcgBhAGsAdAAr AXYAaQAgAGEAawB0ACsBdgBzACAAdQBuACAAaQBuAHQAZQBsAGUAawB0AHUAAQFsAGkAIAB1AG4A IABpAG4AZgBvAHIAbQBhAHQAKwF2AGkAIABpAHoAZwBsACsBdABvAGoAbwBhAXMAIABsAGEAYgBk AGEAcgArAWIAYQBzACAAcABhAHMAAQFrAHUAbQBzACAAagBhAHUAbgBpAGUAYQFpAGUAbQAuAA0A DQBMAGkAZQBsAHMAIABwAGEAbABkAGkAZQBzACAAbQBrAXMAdQAgAGEAdABiAGEAbABzAHQAKwF0 AAEBagBpAGUAbQA6ACAAUgArAWcAYQBzACAARABvAG0AZQBpACwAIABBAEMAQwBFAE4AVABVAFIA RQAsACAAUgBJAE0ASQAuACAASwABASAAYQByACsBIABwAGEAbABkAGkAZQBzACAAZAByAGEAdQBn AGkAZQBtAC4AbAB2ACwAIABMAFQAVgAsACAARABJAEUATgBBACwAIAA1AG0AaQBuACwAIABLAG8A bgB0AGkAIABCAHUAcwBzACwAIABBAGwAZABhAHIAaQBzACwAIABEAG8AdQBiAGwAZQAgAEMAbwBm AGYAZQBlACwAIABQAHIAbwBXAGUAYgAsACAAUgArAWcAYQBzACAAWgBvAG8AZAABAXIAegBzAC4A DQANAFYAYQBpAHIAAQFrACAAaQBuAGYAbwAgABMAIABIAFkAUABFAFIATABJAE4ASwAgACIAaAB0 AHQAcAA6AC8ALwB3AHcAdwAuAHMAdAB1AGQAZQBuAHQAcABhAHIAdAB5AC4AbAB2ACIAIAAUAHcA dwB3AC4AcwB0AHUAZABlAG4AdABwAGEAcgB0AHkALgBsAHYAFQAuAA0ADQAxADMALgAwADkALgAy ADAAMAA3AA0ADQANAA0AUwBhAGcAYQB0AGEAdgBvAGoAYQANAFMAYQBuAGQAYQAgAEIAbABvAG0A awBhAGwAbgBhAA0ADQBSAGUAZABpACMBEwFqAGEADQBBAGcAcgBpAHMAIABBAG0AZQByAGkAawBz AA0AMgA2ADQANgAxADEAMAAxAA0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADGGAAA6hgAAPwYAAD+GAAA RBkAAFQZAACYGQAAnBkAAAwaAAAOGgAAEBoAAGQbAABmGwAAgBsAAIIbAADSGwAA1BsAAPobAAD8 GwAAABwAAAIcAAAWHAAAGBwAAB4cAAA0HAAAUhwAAFQcAACWHAAA+vLr4dPh0+HTzMjEwLi0uKu4 wLTIxMjEpMTIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADBVopQq8ABZopQq8AAAQFWgGBf4AFmjvdpsAMEoQ AAAGFmjvdpsAAA8DagAAAAAWaO92mwBVCAEGFmgDHEgAAAYWaLpotwAABhZopQq8AAAMFWhPOIMA FmilCrwAABoVaKUKvAAWaKUKvAA1CIFdCIFtSAUEc0gFBAASFWilCrwAFmilCrwANQiBXQiBAAwW aKUKvAA1CIFdCIEADxVopQq8ABZopQq8AF0IgQkWaKUKvABdCIEAG1QcAABWHAAAaBwAAIQcAACW HAAA+gAAAAAAAAAAAAAAAPoAAAAAAAAAAAAAAAD6AAAAAAAAAAAAAAAA+gAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAGdkpQq8AAAELAAxkGgBH7CCLiCwxkEhsKUG IrBSAyOQbgQkkG4EJbAAABewxAIYsMQCDJDEAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABeBBEAEgABAAsBDwAHAAAAAAAA AAAABAAIAAAAmAAAAJ4AAACeAAAAngAAAJ4AAACeAAAAngAAAJ4AAACeAAAANgYAADYGAAA2BgAA NgYAADYGAAA2BgAANgYAADYGAAA2BgAAdgIAAHYCAAB2AgAAdgIAAHYCAAB2AgAAdgIAAHYCAAB2 AgAANgYAADYGAAA2BgAANgYAADYGAAA2BgAAPgIAADYGAAA2BgAANgYAADYGAAA2BgAANgYAADYG AAA2BgAANgYAADYGAAA2BgAANgYAADYGAAA2BgAANgYAADYGAAA2BgAANgYAADYGAAA2BgAANgYA ADYGAAA2BgAANgYAADYGAAA2BgAANgYAAKgAAAA2BgAANgYAABYAAAA2BgAANgYAADYGAAA2BgAA NgYAADYGAAA2BgAANgYAALgAAAA2BgAANgYAADYGAAA2BgAANgYAADYGAAA2BgAANgYAADYGAAA2 BgAANgYAADYGAABoAQAASAEAADYGAAA2BgAANgYAADYGAAA2BgAANgYAADYGAAA2BgAANgYAADYG AAA2BgAANgYAADYGAAA2BgAANgYAADYGAAA2BgAANgYAADYGAAA2BgAANgYAADYGAAA2BgAANgYA ADYGAAA2BgAANgYAADYGAAA2BgAANgYAADYGAAA2BgAANgYAADYGAAA2BgAANgYAADYGAAA2BgAA NgYAADYGAAA2BgAANgYAADYGAAA2BgAANgYAADYGAAA2BgAANgYAADYGAAA2BgAANgYAADYGAAA2 BgAANgYAADYGAAA2BgAANgYAADYGAAA2BgAANgYAADYGAAA2BgAANgYAADYGAAA2BgAAsAMAADYG AAAyBgAAGAAAAMADAADQAwAA4AMAAPADAAAABAAAEAQAACAEAAAwBAAAQAQAAFAEAABgBAAAcAQA AIAEAACQBAAAwAMAANADAADgAwAA8AMAAAAEAAAQBAAAMgYAACgCAADYAQAA6AEAACAEAAAwBAAA QAQAAFAEAABgBAAAcAQAAIAEAACQBAAAwAMAANADAADgAwAA8AMAAAAEAAAQBAAAIAQAADAEAABA BAAAUAQAAGAEAABwBAAAgAQAAJAEAADAAwAA0AMAAOADAADwAwAAAAQAABAEAAAgBAAAMAQAAEAE AABQBAAAYAQAAHAEAACABAAAkAQAAMADAADQAwAA4AMAAPADAAAABAAAEAQAACAEAAAwBAAAQAQA AFAEAABgBAAAcAQAAIAEAACQBAAAwAMAANADAADgAwAA8AMAAAAEAAAQBAAAIAQAADAEAABABAAA UAQAAGAEAABwBAAAgAQAAJAEAADAAwAA0AMAAOADAADwAwAAAAQAABAEAAAgBAAAMAQAAEAEAABQ BAAAYAQAAHAEAACABAAAkAQAADgBAABYAQAA+AEAAAgCAAAYAgAAVgIAAH4CAAAUAAAAX0gBBG1I CQRuSAkEc0gJBHRICQQAAAAAQAAAYPH/AgBAAAwQAAAAAAAAAAAGAE4AbwByAG0AYQBsAAAAAgAA ABgAQ0oYAF9IAQRhShgAbUgmBHNIJgR0SBkEAAAAAAAAAAAAAAAAAAAAAAAARABBYPL/oQBEAAwB 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 xnzSKn914qN74OgtuN+fMCVNMME3JYGh9RyYPIDktxzN0o2/AAAA//8DAFBLAwQUAAYACAAAACEA DdGQn7YAAAAbAQAAJwAAAHRoZW1lL3RoZW1lL19yZWxzL3RoZW1lTWFuYWdlci54bWwucmVsc4SP TQrCMBSE94J3CG9v07oQkSbdiNCt1AOE5DUNNj8kUeztDa4sCC6HYb6ZabuXnckTYzLeMWiqGgg6 6ZVxmsFtuOyOQFIWTonZO2SwYIKObzftFWeRSyhNJiRSKC4xmHIOJ0qTnNCKVPmArjijj1bkIqOm Qci70Ej3dX2g8ZsBfMUkvWIQe9UAGZZQmv+z/TgaiWcvHxZd/lFBc9mFBSiixszgI5uqTATKW7q6 xN8AAAD//wMAUEsBAi0AFAAGAAgAAAAhAIKKvBP6AAAAHAIAABMAAAAAAAAAAAAAAAAAAAAAAFtD b250ZW50X1R5cGVzXS54bWxQSwECLQAUAAYACAAAACEApdan58AAAAA2AQAACwAAAAAAAAAAAAAA AAArAQAAX3JlbHMvLnJlbHNQSwECLQAUAAYACAAAACEAa3mWFoMAAACKAAAAHAAAAAAAAAAAAAAA AAAUAgAAdGhlbWUvdGhlbWUvdGhlbWVNYW5hZ2VyLnhtbFBLAQItABQABgAIAAAAIQCWta3ilgYA AFAbAAAWAAAAAAAAAAAAAAAAANECAAB0aGVtZS90aGVtZS90aGVtZTEueG1sUEsBAi0AFAAGAAgA AAAhAA3RkJ+2AAAAGwEAACcAAAAAAAAAAAAAAAAAmwkAAHRoZW1lL3RoZW1lL19yZWxzL3RoZW1l TWFuYWdlci54bWwucmVsc1BLBQYAAAAABQAFAF0BAACWCgAAAAA8P3htbCB2ZXJzaW9uPSIxLjAi IGVuY29kaW5nPSJVVEYtOCIgc3RhbmRhbG9uZT0ieWVzIj8+DQo8YTpjbHJNYXAgeG1sbnM6YT0i aHR0cDovL3NjaGVtYXMub3BlbnhtbGZvcm1hdHMub3JnL2RyYXdpbmdtbC8yMDA2L21haW4iIGJn MT0ibHQxIiB0eDE9ImRrMSIgYmcyPSJsdDIiIHR4Mj0iZGsyIiBhY2NlbnQxPSJhY2NlbnQxIiBh Y2NlbnQyPSJhY2NlbnQyIiBhY2NlbnQzPSJhY2NlbnQzIiBhY2NlbnQ0PSJhY2NlbnQ0IiBhY2Nl bnQ1PSJhY2NlbnQ1IiBhY2NlbnQ2PSJhY2NlbnQ2IiBobGluaz0iaGxpbmsiIGZvbEhsaW5rPSJm b2xIbGluayIvPgAAAAAZCAAADAAAIgAAAAD/////AAgAAMYYAACWHAAACQAAAA8AAAAACAAAVBwA AJYcAAAKAAAAEAAAAI4HAAC3BwAAywcAABkIAAATWBT/FYAPAADwOAAAAAAABvAYAAAAAggAAAIA AAABAAAAAQAAAAEAAAACAAAAQAAe8RAAAAD//wAAAAD/AICAgAD3AAAQAA8AAvCSAAAAEAAI8AgA AAABAAAAAQQAAA8AA/AwAAAADwAE8CgAAAABAAnwEAAAAAAAAAAAAAAAAAAAAAAAAAACAArwCAAA AAAEAAAFAAAADwAE8EIAAAASAArwCAAAAAEEAAAADgAAUwAL8B4AAAC/AQAAEADLAQAAAAD/AQAA CAAEAwkAAAA/AwEAAQAAABHwBAAAAAEAAAD//wEAAAALADAALgAxAF8AdABhAGIAbABlADEANgA5 BQAAGwgAAAAAAAA5BQAAGwgAAAAAAAB8AAAAhgAAAIcAAACJAAAAkgAAAJkAAADnAAAAAQEAAM4C AADdAgAA5AIAAPUCAAAUAwAAJQMAAK8DAACwAwAAsgMAAMYDAADOAwAABQQAAAYEAAAHBAAADAQA ABIEAAAUBAAAFgQAABsEAAArBAAALwQAAEYEAABUBAAAZAQAAGYEAABnBAAAaQQAAI0EAACPBAAA mgQAAJwEAACnBAAAqQQAAKoEAACsBAAArgQAALAEAAASBQAAHgUAAB8FAAAiBQAALAUAAC0FAAA2 BQAAOQUAAJ0FAACfBQAAsAUAALIFAADCBQAAxAUAAM0FAADTBQAA5QUAAOgFAADwBQAA8gUAAPUF AAD7BQAALwYAADEGAAA1BgAANwYAAD0GAAA/BgAATAYAAE4GAABfBgAAZAYAAHgGAAB5BgAAnAYA AJ0GAADUBgAA1gYAAOUGAADpBgAA9wYAAP8GAAAEBwAABQcAABUHAAAaBwAAPgcAAD8HAABEBwAA RQcAAHIHAAB3BwAAgAcAAIIHAACGBwAAiQcAAI4HAADPBwAA2QcAAN0HAADoBwAA7gcAAPcHAAD5 BwAAGAgAABsIAAAHAAUABwAFAAcABQAHAAUABwAFAAcABQAHAAUABwAFAAcABQAHAAUABwAFAAcA BQAHAAUABwAFAAcABQAHAAUABwAFAAcABQAHAAUABwAFAAcABQAHAAUABwAFAAcABQAHAAUABwAE AAcABQAHAAUABwAFAAcABQAHAAUABwAFAAcABQAHAAUABwAFAAcABQAHAAUABwAFAAcABQAHAAUA BwAFAAcABQAHAAUABwAFAAcABQAHAAUABwAFAAcABQAHAAUABwAFAAcABQAHAAUABwAFAAcABQAH AAUABwAAAAAAEAAAABEAAAAoAAAAKQAAADIAAAA0AAAAiAEAAIoBAABIBAAASgQAABQFAAA3BQAA OQUAAOUFAADoBQAALwYAADEGAADUBgAA1gYAAIAHAACCBwAAzQcAAM8HAADZBwAA3QcAAOcHAADo BwAA9wcAAPkHAAABCAAAAggAAA8IAAAQCAAAGAgAABsIAAAFAAcABQAHAAUABwAFAAcABQAHAAUA BAAHAAUABwAFAAcABQAHAAUABwAFAAcABQAHAAUABwAFAAcABQAHAAUABwAFAAcAAAAAAIYAAACH AAAAzgIAAPUCAABkBAAAjQQAAI4EAACbBAAAnAQAALAEAAASBQAANwUAAPAFAADVBgAA1gYAAM4H AADPBwAA2QcAANoHAADdBwAA6AcAABgIAAAbCAAAAwAEAAMABAADAAQAAwAEAAMABAADAAQAAwAE AAMABAADAAQAAwAEAAMABAAHAAAAAADOAgAA9QIAACwFAAA2BQAAjgcAAMwHAADOBwAAzgcAABgI AAAbCAAAAwAEAAMABAADAAQAAwAEAAMABwABANkcA1Ue07rY/w//D/8P/w//D/8P/w//D/8PAAAB AAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAGAAAD4TQAhGEmP4VxgUAAdACBl6E0AJghJj+AgAAAC4A AQAAAAQAAQAAAAAAAAAAAAAAAAAAAAAAABgAAA+EoAURhJj+FcYFAAGgBQZehKAFYISY/gIAAQAu AAEAAAAAgAEAAAAAAAAAAAAAAAAAAAAAAAAYAAAPhHAIEYSY/hXGBQABcAgGXoRwCGCEmP4CAAIA LgABAAAAAIABAAAAAAAAAAAAAAAAAAAAAAAAGAAAD4RACxGEmP4VxgUAAUALBl6EQAtghJj+AgAD AC4AAQAAAACAAQAAAAAAAAAAAAAAAAAAAAAAABgAAA+EEA4RhJj+FcYFAAEQDgZehBAOYISY/gIA BAAuAAEAAAAAgAEAAAAAAAAAAAAAAAAAAAAAAAAYAAAPhOAQEYSY/hXGBQAB4BAGXoTgEGCEmP4C AAUALgABAAAAAIABAAAAAAAAAAAAAAAAAAAAAAAAGAAAD4SwExGEmP4VxgUAAbATBl6EsBNghJj+ AgAGAC4AAQAAAACAAQAAAAAAAAAAAAAAAAAAAAAAABgAAA+EgBYRhJj+FcYFAAGAFgZehIAWYISY /gIABwAuAAEAAAAAgAEAAAAAAAAAAAAAAAAAAAAAAAAYAAAPhFAZEYSY/hXGBQABUBkGXoRQGWCE mP4CAAgALgABAAAA2RwDVQAAAAAAAAAAAAAAAP///////wEAAAAAAP//AQAAAAAAAQAAfhdaAAAA AAAAAAAAAQIAAgATAAAABAAAAAgAAADlAAAAAAAAABIAAAAVKQ4APCAQAAMcSADBFFAArgJuAOli dgD6T3sATziDALwbkABadJIA73abAHN9owCzNqkAPSy3ALpotwCwEbkApQq8ANAz6gAmYewAAAAA ABkIAAAbCAAAAAAAAAEAAAD/QAIcAAAAAAAAAM4EAAAZCAAAYAAACAAAAABgAAAWAAAAAP//AQAA AAcAVQBuAGsAbgBvAHcAbgD//wEACAAAAAAAAAAAAAAA//8BAAAAAAD//wAAAgD//wAAAAD//wAA AgD//wAAAAAEAAAARx6QAboAAgIGAwUEBQIDBIcqACAAAACACAAAAAAAAAD/AQAAAAAAAFQAaQBt AGUAcwAgAE4AZQB3ACAAUgBvAG0AYQBuAAAANR6QAQIABQUBAgEHBgIFBwAAAAAAAAAQAAAAAAAA AAAAAACAAAAAAFMAeQBtAGIAbwBsAAAAMy6QAboAAgsGBAICAgICBIcqACAAAACACAAAAAAAAAD/ AQAAAAAAAEEAcgBpAGEAbAAAAEEekAG6AAIEBQMFBAYDAgTvAgCg6yAAQgAAAAAAAAAAnwAAAAAA AABDAGEAbQBiAHIAaQBhACAATQBhAHQAaAAAACIABADxCIgYAPDEAgAAaAEAAAAAA2q5hhhquYYA AAAABgAIAAAANQEAAOQGAAABAAQAAAAEAAMQDgAAADUBAADkBgAAAQAEAAAADgAAAAAAAAAhAwDw EAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAClBm4EtAC0AIGBcjQAABAAGQBkAAAAGQAAABUI AAAVCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAgAAAAAAAAAAAAAyg1EA8BAACAD//QEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAI SFAAAAAACfD/DwEIAT8AAOMEAAD///9/////f////3////9/////f////3////9/sBG5AAAEAAAy AAAAAAAAAAAAAAAAAAAAAAAAAAAAIQQAAAAAAAAAAAAAAAAAAAAAAAAQHAAAAwAAAAAAAAAAAHgA AAB4AAAAAAAAAAAAAACgBQAA//8SAAAAAAAAABAAUwB0AHUAZABlAG4AdAB1ACAAUAAAAVIAVABJ AEoAUwAAAAAAAAAPAFMAYQBuAGQAYQAgAEIAbABvAG0AawBhAGwAbgBhAAMAQQBBAEEAAAAAAAAA AAAAAAAAAAAAAAAAAAAQAAAABgAAAAEAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAA/v8AAAUBAgAAAAAAAAAAAAAAAAAAAAAAAQAAAOCFn/L5T2gQ q5EIACsns9kwAAAAfAEAABEAAAABAAAAkAAAAAIAAACYAAAAAwAAALQAAAAEAAAAwAAAAAUAAADY AAAABgAAAOQAAAAHAAAA8AAAAAgAAAAAAQAACQAAAAwBAAASAAAAGAEAAAoAAAA4AQAADAAAAEQB AAANAAAAUAEAAA4AAABcAQAADwAAAGQBAAAQAAAAbAEAABMAAAB0AQAAAgAAAOkEAAAeAAAAFAAA AFN0dWRlbnR1IFDCUlRJSlMAAAAAHgAAAAQAAAAAAAAAHgAAABAAAABTYW5kYSBCbG9ta2FsbmEA HgAAAAQAAAAAAAAAHgAAAAQAAAAAAAAAHgAAAAgAAABOb3JtYWwAAB4AAAAEAAAAQUFBAB4AAAAE AAAANgAAAB4AAAAYAAAATWljcm9zb2Z0IE9mZmljZSBXb3JkAAAAQAAAAAAwGh4BAAAAQAAAAAAa JlvD9ccBQAAAAADYKkrG9ccBAwAAAAEAAAADAAAANQEAAAMAAADkBgAAAwAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAP7/AAAFAQIAAAAAAAAAAAAAAAAAAAAAAAIAAAAC1c3VnC4bEJOXCAArLPmu RAAAAAXVzdWcLhsQk5cIACss+a5AAQAA/AAAAAwAAAABAAAAaAAAAA8AAABwAAAABQAAAIAAAAAG AAAAiAAAABEAAACQAAAAFwAAAJgAAAALAAAAoAAAABAAAACoAAAAEwAAALAAAAAWAAAAuAAAAA0A AADAAAAADAAAAN0AAAACAAAA6QQAAB4AAAAIAAAAbWFqYXMAAAADAAAADgAAAAMAAAAEAAAAAwAA ABUIAAADAAAAAAAMAAsAAAAAAAAACwAAAAAAAAALAAAAAAAAAAsAAAAAAAAAHhAAAAEAAAARAAAA U3R1ZGVudHUgUMJSVElKUwAMEAAAAgAAAB4AAAAGAAAAVGl0bGUAAwAAAAEAAAAAuAAAAAMAAAAA AAAAIAAAAAEAAAA4AAAAAgAAAEAAAAABAAAAAgAAAAwAAABfUElEX0hMSU5LUwACAAAA6QQAAEEA AABwAAAABgAAAAMAAAA5AHEAAwAAAAAAAAADAAAAAAAAAAMAAAAFAAAAHwAAABwAAABoAHQAdABw ADoALwAvAHcAdwB3AC4AcwB0AHUAZABlAG4AdABwAGEAcgB0AHkALgBsAHYALwAAAB8AAAABAAAA AAASAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAABAAAAAgAAAAMAAAAEAAAABQAAAAYAAAAHAAAACAAAAAkAAAAKAAAACwAAAAwAAAANAAAA DgAAAA8AAAAQAAAAEQAAAP7///8TAAAAFAAAABUAAAAWAAAAFwAAABgAAAAZAAAAGgAAABsAAAAc AAAAHQAAAB4AAAAfAAAAIAAAACEAAAAiAAAA/v///yQAAAAlAAAAJgAAACcAAAAoAAAAKQAAACoA AAD+////LAAAAC0AAAAuAAAALwAAADAAAAAxAAAAMgAAAP7////9////NQAAAP7////+/////v// //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// /////1IAbwBvAHQAIABFAG4AdAByAHkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAWAAUB//////////8DAAAABgkCAAAAAADAAAAAAAAARgAAAAAAAAAAAAAAANDr n0vG9ccBNwAAAIAAAAAAAAAAMQBUAGEAYgBsAGUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4AAgH/////BQAAAP////8AAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAASAAAAQSAAAAAAAABXAG8AcgBkAEQAbwBjAHUAbQBlAG4AdAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGgACAQEAAAD//////////wAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAuIgAAAAAAAAUAUwB1AG0AbQBh AHIAeQBJAG4AZgBvAHIAbQBhAHQAaQBvAG4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAoAAIB AgAAAAQAAAD/////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIwAAAAAQAAAA AAAABQBEAG8AYwB1AG0AZQBuAHQAUwB1AG0AbQBhAHIAeQBJAG4AZgBvAHIAbQBhAHQAaQBvAG4A AAAAAAAAAAAAADgAAgH///////////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAArAAAAABAAAAAAAAABAEMAbwBtAHAATwBiAGoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEgACAP///////////////wAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB5AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////////////////AAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/ //////////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAABAAAA/v////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// /wEA/v8DCgAA/////wYJAgAAAAAAwAAAAAAAAEYnAAAATWljcm9zb2Z0IE9mZmljZSBXb3JkIDk3 LTIwMDMgRG9jdW1lbnQACgAAAE1TV29yZERvYwAQAAAAV29yZC5Eb2N1bWVudC44APQ5snEAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA ------=_Part_8802_28973416.1189661104602-- schleuder-3.6.0/spec/fixtures/mails/bounces/tt_bounce_15.txt.eml000066400000000000000000000145221401002544500246470ustar00rootroot00000000000000Delivered-To: agris.ameriks@gmail.com Received: by 10.66.241.15 with SMTP id o15cs57761ugh; Wed, 29 Aug 2007 06:08:21 -0700 (PDT) Received: by 10.78.177.3 with SMTP id z3mr345635hue.1188392900264; Wed, 29 Aug 2007 06:08:20 -0700 (PDT) Return-Path: <> Received: from mail1.rimibaltic.com (mail1.rimibaltic.com [82.135.221.93]) by mx.google.com with ESMTP id 35si5978420huc.2007.08.29.06.08.13; Wed, 29 Aug 2007 06:08:20 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of mail1.rimibaltic.com designates 82.135.221.93 as permitted sender) client-ip=82.135.221.93; Authentication-Results: mx.google.com; spf=pass smtp.mail=; dkim=hardfail (test mode) header.i=@gmail.com Received: from LT-RELAY (LT-RELAY [127.0.0.1]) by LV-RELAY (Postfix) with SMTP id BB603418F for ; Wed, 29 Aug 2007 16:08:03 +0300 (EEST) Received: from rimilt01.rimi.lan (unknown [10.18.0.224]) by mail1.rimibaltic.com (Postfix) with ESMTP id 58EE0418D for ; Wed, 29 Aug 2007 16:08:01 +0300 (EEST) DKIM-Signature: a=rsa-sha1; c=relaxed/relaxed; d=gmail.com; s=beta; h=domainkey-signature:received:received:message-id:date:from:to:subject:mime-version:content-type; b=CZ9QIO+5UC0ZclbYqmqs89IO2AWxqJeghMU783zhJTGdMEDpiIbj6737zmC4iP7ZEj+j6hLtvYrBIA+oErYDTTzYht/2B2JHLzalRxWjtqekJD/tLV4R5mUVEg9Y8H/aZSj2YKo2h+EWE1NMHyzZgCN47wKiDEFC/g+YnG93K6k= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=beta; h=received:message-id:date:from:to:subject:mime-version:content-type; b=N2pzQqRtteBggnskinEjcQuPTbTCoymrnmzqX7y0xuc4pQUDSd+/89buaDxOK+qbTr7YT+4hgOCzCTwkk9Tr5AXUD+6MMvlDHANDZ3UkGmrwhdAkf/67SGVhCT64aIIVXJ3BcLR71HRLabzkNgNyCp5+Zh/nkMNMnAmqwWIEuXo= Date: Wed, 29 Aug 2007 16:07:26 +0300 From: Postmaster@rimibaltic.com To: "Agris Ameriks" Subject: DELIVERY FAILURE: Recipient user name info (info@rimibaltic.com) not unique. Several matches found in Domino Directory. MIME-Version: 1.0 X-MIMETrack: Itemize by SMTP Server on RIMILT01/RIMILT/RIMI(Release 6.5.3|September 14, 2004) at 2007.08.29 16:09:02, Serialize by Router on RIMILT01/RIMILT/RIMI(Release 6.5.3|September 14, 2004) at 2007.08.29 16:09:03, Serialize complete at 2007.08.29 16:09:03 Message-ID: Content-Type: multipart/report; report-type=delivery-status; boundary="==IFJRGLKFGIR29037UHRUHIHD" --==IFJRGLKFGIR29037UHRUHIHD Content-Type: text/plain; charset=windows-1257 Content-Transfer-Encoding: quoted-printable Your message Subject: Atbalsta l=FBgums was not delivered to: info@rimibaltic.com because: Recipient user name info (info@rimibaltic.com) not unique. Several match= es found in Domino Directory. --==IFJRGLKFGIR29037UHRUHIHD Content-Type: message/delivery-status Reporting-MTA: dns;rimilt01.rimi.lan Final-Recipient: rfc822;info@rimibaltic.com Action: failed Status: 5.0.0 Diagnostic-Code: X-Notes; Recipient user name info (info@rimibaltic.com ) not unique. Several matches found in Domino Directory. --==IFJRGLKFGIR29037UHRUHIHD Content-Type: message/rfc822 Received: from mail1.rimibaltic.com ([172.16.250.54]) by rimilt01.rimi.lan (Lotus Domino Release 6.5.3) with SMTP id 2007082916090093-229401 ; Wed, 29 Aug 2007 16:09:00 +0300 Received: from LT-RELAY (LT-RELAY [127.0.0.1]) by LV-RELAY (Postfix) with SMTP id 11DAF418F for ; Wed, 29 Aug 2007 16:07:54 +0300 (EEST) Received: from nf-out-0910.google.com (nf-out-0910.google.com [64.233.182.186]) by mail1.rimibaltic.com (Postfix) with SMTP id 375504198 for ; Wed, 29 Aug 2007 16:07:46 +0300 (EEST) Received: by nf-out-0910.google.com with SMTP id k4so180273nfd for ; Wed, 29 Aug 2007 06:07:45 -0700 (PDT) Received: by 10.82.114.3 with SMTP id m3mr1324122buc.1188392846495; Wed, 29 Aug 2007 06:07:26 -0700 (PDT) Received: by 10.66.241.15 with HTTP; Wed, 29 Aug 2007 06:07:26 -0700 (PDT) DKIM-Signature: a=rsa-sha1; c=relaxed/relaxed; d=gmail.com; s=beta; h=domainkey-signature:received:received:message-id:date:from:to:subject:mime-version:content-type; b=CZ9QIO+5UC0ZclbYqmqs89IO2AWxqJeghMU783zhJTGdMEDpiIbj6737zmC4iP7ZEj+j6hLtvYrBIA+oErYDTTzYht/2B2JHLzalRxWjtqekJD/tLV4R5mUVEg9Y8H/aZSj2YKo2h+EWE1NMHyzZgCN47wKiDEFC/g+YnG93K6k= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=beta; h=received:message-id:date:from:to:subject:mime-version:content-type; b=N2pzQqRtteBggnskinEjcQuPTbTCoymrnmzqX7y0xuc4pQUDSd+/89buaDxOK+qbTr7YT+4hgOCzCTwkk9Tr5AXUD+6MMvlDHANDZ3UkGmrwhdAkf/67SGVhCT64aIIVXJ3BcLR71HRLabzkNgNyCp5+Zh/nkMNMnAmqwWIEuXo= Date: Wed, 29 Aug 2007 16:07:26 +0300 From: "Agris Ameriks" To: Agris.Ameriks@gmail.com Subject: =?ISO-8859-13?Q?Atbalsta_l=FBgums?= MIME-Version: 1.0 X-MIMETrack: Itemize by SMTP Server on RIMILT01/RIMILT/RIMI(Release 6.5.3|September 14, 2004) at 2007.08.29 16:09:02, Serialize by Router on RIMILT01/RIMILT/RIMI(Release 6.5.3|September 14, 2004) at 2007.08.29 16:09:03 Message-ID: Content-Type: multipart/mixed; boundary="----=_Part_3572_23058828.1188392846046" ------=_Part_3572_23058828.1188392846046 Content-Transfer-Encoding: base64 Content-Type: text/plain; charset=ISO-8859-13 Content-Disposition: inline TGFiZGllbiEKCjE1LnNlcHRlbWJy7iBFc3BsYW7iZOcgbm90aWtzIHN0dWRlbnR1IHBhc+JrdW1z LgoKVudsYW1pZXMgbPtndCBK+3N1IGZpbmFuc2nibG8gYXRiYWxzdHUgc2VtaW7icmEgdGVsdGlq LgoKUGllbGlrdW3iOgp4KSBQcmV6ZW504mNpamEKCi0tIApDZXLuYuIgdXogc2FkYXJi7mJ1LApB Z3JpcyBBbWVyaWtzCk1vYi50ZWwuIDIgNjQ2MTEwMQpFLXBhc3RzOiBBZ3Jpcy5BbWVyaWtzQGdt YWlsLmNvbQo= ------=_Part_3572_23058828.1188392846046 X-Attachment-Id: f_f5xue1gd Content-Type: application/vnd.ms-powerpoint; name="StudentuPartijsV2.pps" Content-Disposition: attachment; filename="StudentuPartijsV2.pps"; filename="StudentuPartijsV2.pps" Content-Transfer-Encoding: base64 0M8R4KGxGuEAAAAAAAAAAAAAAAAAAAAAPgADAP7/CQAGAAAAAAAAAAAAAAAWAAAAjgoAAAAAAAAA EAAA/v///wAAAAD+////AAAAAHgKAAB5CgAAegoAAHsKAAB8CgAAfQoAAH4KAAB/CgAAgAoAAIEK AACCCgAAgwoAAIQKAACFCgAAhgoAAIcKAACICgAAiQoAAIoKAACLCgAAjAoAAI0KAAD///////// AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAttachmentTruncated== ------=_Part_3572_23058828.1188392846046-- --==IFJRGLKFGIR29037UHRUHIHD-- schleuder-3.6.0/spec/fixtures/mails/bounces/tt_bounce_16.txt.eml000066400000000000000000000111721401002544500246460ustar00rootroot00000000000000Delivered-To: agris.ameriks@gmail.com Received: by 10.67.102.1 with SMTP id e1cs84341ugm; Wed, 12 Sep 2007 22:25:35 -0700 (PDT) Received: by 10.67.103.12 with SMTP id f12mr2624608ugm.1189661135681; Wed, 12 Sep 2007 22:25:35 -0700 (PDT) Return-Path: <> Received: from blackbird.grafton.lv (blackbird.grafton.lv [159.148.13.8]) by mx.google.com with ESMTP id d26si2053796nfh.2007.09.12.22.25.32; Wed, 12 Sep 2007 22:25:35 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of blackbird.grafton.lv designates 159.148.13.8 as permitted sender) client-ip=159.148.13.8; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of blackbird.grafton.lv designates 159.148.13.8 as permitted sender) smtp.mail= Received: by blackbird.grafton.lv (Postfix) id 39C5162006D; Thu, 13 Sep 2007 08:25:32 +0300 (EEST) Date: Thu, 13 Sep 2007 08:25:32 +0300 (EEST) From: MAILER-DAEMON@blackbird.grafton.lv (Mail Delivery System) Subject: Undelivered Mail Returned to Sender To: agris.ameriks@gmail.com Auto-Submitted: auto-replied MIME-Version: 1.0 Content-Type: multipart/report; report-type=delivery-status; boundary="EC740620064.1189661132/blackbird.grafton.lv" Message-Id: <20070913052532.39C5162006D@blackbird.grafton.lv> This is a MIME-encapsulated message. --EC740620064.1189661132/blackbird.grafton.lv Content-Description: Notification Content-Type: text/plain; charset=us-ascii This is the mail system at host blackbird.grafton.lv. I'm sorry to have to inform you that your message could not be delivered to one or more recipients. It's attached below. For further assistance, please send mail to postmaster. If you do so, please include this problem report. You can delete your own text from the attached returned message. The mail system (expanded from ): maildir delivery failed: Sorry, the user's maildir has overdrawn his diskspace quota, please try again later. --EC740620064.1189661132/blackbird.grafton.lv Content-Description: Delivery report Content-Type: message/delivery-status Reporting-MTA: dns; blackbird.grafton.lv X-Postfix-Queue-ID: EC740620064 X-Postfix-Sender: rfc822; agris.ameriks@gmail.com Arrival-Date: Thu, 13 Sep 2007 08:25:29 +0300 (EEST) Final-Recipient: rfc822; jekaterina@tv5.lv Original-Recipient: rfc822;notikums@tv5.lv Action: failed Status: 5.2.3 Diagnostic-Code: X-Postfix; maildir delivery failed: Sorry, the user's maildir has overdrawn his diskspace quota, please try again later. --EC740620064.1189661132/blackbird.grafton.lv Content-Description: Undelivered Message Headers Content-Type: text/rfc822-headers Received: from hu-out-0506.google.com (hu-out-0506.google.com [72.14.214.233]) by blackbird.grafton.lv (Postfix) with ESMTP id 1B48675C04F for ; Thu, 13 Sep 2007 08:25:29 +0300 (EEST) Received: by hu-out-0506.google.com with SMTP id 28so167829hug for ; Wed, 12 Sep 2007 22:25:29 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=beta; h=domainkey-signature:received:received:message-id:date:from:to:subject:cc:mime-version:content-type; bh=L2SyivlqHxtTjH5g4+fQw5fs6kGsOHDdZAIpOVCV8D8=; b=RM2JXrCYFBhkLe4yd6MxT0vmzvsHsyA32ylCdGEs6dezOLBcyT3lgh/t+qJ6XgJpJyDA6z2lEt3GRh8UvPhjD4Kl/Y6IuiNcuzZWVAXZ7MGTBiv+3wSBCU+pyQsQDGkZWLkBTX6MgAthHhOzZAhXnyfM1Oe1Dgg0Q2UCaz9bXY4= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=beta; h=received:message-id:date:from:to:subject:cc:mime-version:content-type; b=FRTW/6SXI8LlxwFqs1q82QJK0pNGrTWJ1KVsKIqnA++p++EGtHGryiAagnHG4s91WGGZ8IeRnQhiEPDqyG3GHqpYZR3GzmsluDdLGsKhi75yYfwXq8p+XAQ9AGGMFwYpq2RCrumuHNWWnAPLFvkIQePM/4aLKJ9Ms/ORwiinMXY= Received: by 10.67.26.7 with SMTP id d7mr2639740ugj.1189661104603; Wed, 12 Sep 2007 22:25:04 -0700 (PDT) Received: by 10.67.102.1 with HTTP; Wed, 12 Sep 2007 22:25:04 -0700 (PDT) Message-ID: Date: Thu, 13 Sep 2007 08:25:04 +0300 From: "Agris Ameriks" To: Agris.Ameriks@gmail.com Subject: =?ISO-8859-13?Q?15.septembr=EE_Studentu_P=E2rtijs!?= Cc: "=?ISO-8859-13?Q?J=E2nis_Erts?=" , "Edgars Gutkis" , "Toms Beinerts" MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="----=_Part_8802_28973416.1189661104602" X-GRAFTON-MailScanner-Information: Scanned by GRAFTON mailscanner service X-GRAFTON-MailScanner: Found to be clean X-GRAFTON-MailScanner-From: agris.ameriks@gmail.com X-Spam-Status: No --EC740620064.1189661132/blackbird.grafton.lv-- schleuder-3.6.0/spec/fixtures/mails/bounces/tt_bounce_17.txt.eml000066400000000000000000000101311401002544500246410ustar00rootroot00000000000000Delivered-To: agris.ameriks@gmail.com Received: by 10.67.22.18 with SMTP id z18cs119120ugi; Wed, 12 Mar 2008 14:31:25 -0700 (PDT) Received: by 10.82.116.15 with SMTP id o15mr221186buc.11.1205357484938; Wed, 12 Mar 2008 14:31:24 -0700 (PDT) Return-Path: <> Received: from mail.burusports.lv ([80.81.51.32]) by mx.google.com with SMTP id x6si2994337gvf.0.2008.03.12.14.31.23; Wed, 12 Mar 2008 14:31:24 -0700 (PDT) Received-SPF: neutral (google.com: 80.81.51.32 is neither permitted nor denied by best guess record for domain of mail.burusports.lv) client-ip=80.81.51.32; Authentication-Results: mx.google.com; spf=neutral (google.com: 80.81.51.32 is neither permitted nor denied by best guess record for domain of mail.burusports.lv) smtp.mail= Message-Id: <47d84bac.06c8100a.7545.ffff934bSMTPIN_ADDED@mx.google.com> Received: (qmail 8085 invoked for bounce); 12 Mar 2008 21:20:16 -0000 Date: 12 Mar 2008 21:20:16 -0000 From: MAILER-DAEMON@mail.burusports.lv To: agris.ameriks@gmail.com Subject: failure notice Hi. This is the qmail-send program at mail.burusports.lv. I'm afraid I wasn't able to deliver your message to the following addresses. This is a permanent error; I've given up. Sorry it didn't work out. : Sorry, no mailbox here by that name. (#5.1.1) --- Below this line is a copy of the message. Return-Path: Received: (qmail 8078 invoked by uid 1010); 12 Mar 2008 21:20:16 -0000 Received: from user-0c6s9jp.cable.mindspring.com (24.110.38.121) by mail.burusports.lv with SMTP; 12 Mar 2008 21:20:16 -0000 Content-Return: allowed X-Mailer: CME-V6.5.4.3; MSN Message-Id: <20080213-12430.11530.qmail@user-0c6s9jp.cable.mindspring.com> To: Subject: RE: MensHealth id 347305 From: MIME-Version: 1.0 Content-Type: text/html; charset="ISO-8859-1" Content-Transfer-Encoding: 7bit Your Alert!!
schleuder-3.6.0/spec/fixtures/mails/bounces/tt_bounce_18.txt.eml000066400000000000000000000101661401002544500246520ustar00rootroot00000000000000Delivered-To: agris.ameriks@gmail.com Received: by 10.100.178.8 with SMTP id a8cs69023anf; Thu, 8 May 2008 23:33:43 -0700 (PDT) Received: by 10.67.119.8 with SMTP id w8mr619138ugm.34.1210314821853; Thu, 08 May 2008 23:33:41 -0700 (PDT) Return-Path: <> Received: by 10.67.119.8 with SMTP id w8mr990983ugm.34; Thu, 08 May 2008 23:33:41 -0700 (PDT) Message-ID: <00148521085105deee044cc66165@googlemail.com> From: Mail Delivery Subsystem To: Agris.Ameriks@gmail.com Subject: Delivery Status Notification (Delay) Date: Thu, 08 May 2008 23:33:41 -0700 (PDT) This is an automatically generated Delivery Status Notification THIS IS A WARNING MESSAGE ONLY. YOU DO NOT NEED TO RESEND YOUR MESSAGE. Delivery to the following recipient has been delayed: welcome6_@one.lv Message will be retried for 1 more day(s) Technical details of temporary failure: TEMP_FAILURE: The recipient server did not accept our requests to connect. Learn more at http://mail.google.com/support/bin/answer.py?answer=7720 [mail2.one.lv. (10): Connection dropped] [mail1.one.lv. (10): Connection dropped] ----- Message header follows ----- Received: by 10.67.119.8 with SMTP id w8mr98269ugm.34.1210139655489; Tue, 06 May 2008 22:54:15 -0700 (PDT) Return-Path: Received: from ?10.43.176.45? ( [212.93.97.166]) by mx.google.com with ESMTPS id e1sm10709566ugf.71.2008.05.06.22.53.48 (version=TLSv1/SSLv3 cipher=RC4-MD5); Tue, 06 May 2008 22:54:14 -0700 (PDT) References: <20080506173511.F23C57F1EA@mail.balticom.lv> Message-Id: <347AE19D-8217-46DB-A64C-D6043980B1C8@gmail.com> From: Agris Ameriks To: Robert Zemaitis <999881@gmail.com> In-Reply-To: <20080506173511.F23C57F1EA@mail.balticom.lv> Content-Type: multipart/alternative; boundary=Apple-Mail-1--95882711 X-Mailer: iPhone Mail (4A93) Mime-Version: 1.0 (iPhone Mail 4A93) Subject: Re: www.1mie.lv Date: Wed, 7 May 2008 08:52:29 +0300 Cc: "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "<7943@inbox.lv>" <7943@inbox.lv>, "" , "" , "" , "" , "" , "" , "" , "" , "" , "" ----- Message body suppressed ----- schleuder-3.6.0/spec/fixtures/mails/bounces/tt_bounce_19.txt.eml000066400000000000000000000030361401002544500246510ustar00rootroot00000000000000Delivered-To: agris.ameriks@gmail.com Received: by 10.142.239.2 with SMTP id m2cs6214wfh; Tue, 21 Oct 2008 02:07:58 -0700 (PDT) Received: by 10.142.237.20 with SMTP id k20mr3599378wfh.225.1224580077680; Tue, 21 Oct 2008 02:07:57 -0700 (PDT) Return-Path: <> Received: by 10.142.237.20 with SMTP id k20mr4333056wfh.225; Tue, 21 Oct 2008 02:07:57 -0700 (PDT) Message-ID: <000e0cd32e0a87764b0459bfc48b@googlemail.com> From: Mail Delivery Subsystem To: agris.ameriks@gmail.com Subject: Delivery Status Notification (Delay) Date: Tue, 21 Oct 2008 02:07:57 -0700 (PDT) This is an automatically generated Delivery Status Notification THIS IS A WARNING MESSAGE ONLY. YOU DO NOT NEED TO RESEND YOUR MESSAGE. Delivery to the following recipient has been delayed: 26461101@sms.id.lv Message will be retried for 2 more day(s) Technical details of temporary failure: Connection was dropped by remote host (SENT_HELO) ----- Message header follows ----- Received: by 10.142.237.20 with SMTP id k20mr2845893wfh.225.1224483056395; Sun, 19 Oct 2008 23:10:56 -0700 (PDT) Received: by 10.142.239.2 with HTTP; Sun, 19 Oct 2008 23:10:56 -0700 (PDT) Message-ID: Date: Mon, 20 Oct 2008 09:10:56 +0300 From: "Agris Ameriks" To: 26461101@sms.id.lv Subject: test MIME-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 7bit Content-Disposition: inline ----- Message body suppressed ----- schleuder-3.6.0/spec/fixtures/mails/bounces/tt_bounce_20.txt.eml000066400000000000000000000026471401002544500246500ustar00rootroot00000000000000Delivered-To: agris.ameriks@gmail.com Received: by 10.142.239.2 with SMTP id m2cs167913wfh; Thu, 23 Oct 2008 10:50:12 -0700 (PDT) Received: by 10.142.237.20 with SMTP id k20mr480333wfh.225.1224784212074; Thu, 23 Oct 2008 10:50:12 -0700 (PDT) Return-Path: <> Received: by 10.142.237.20 with SMTP id k20mr568444wfh.225; Thu, 23 Oct 2008 10:50:12 -0700 (PDT) Message-ID: <000e0cd32e0ae31fa20459ef4b66@googlemail.com> From: Mail Delivery Subsystem To: agris.ameriks@gmail.com Subject: Delivery Status Notification (Failure) Date: Thu, 23 Oct 2008 10:50:12 -0700 (PDT) This is an automatically generated Delivery Status Notification Delivery to the following recipient failed permanently: 26461101@sms.id.lv Technical details of permanent failure: Connection was dropped by remote host (SENT_HELO) ----- Original message ----- Received: by 10.142.237.20 with SMTP id k20mr2845893wfh.225.1224483056395; Sun, 19 Oct 2008 23:10:56 -0700 (PDT) Received: by 10.142.239.2 with HTTP; Sun, 19 Oct 2008 23:10:56 -0700 (PDT) Message-ID: Date: Mon, 20 Oct 2008 09:10:56 +0300 From: "Agris Ameriks" To: 26461101@sms.id.lv Subject: test MIME-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 7bit Content-Disposition: inline Tests ----- End of message ----- schleuder-3.6.0/spec/fixtures/mails/bounces/tt_bounce_21.txt.eml000066400000000000000000000060271401002544500246450ustar00rootroot00000000000000X-Gmail-Received: 7725338024020c2d815c02336798897c551fc80c Delivered-To: agris.ameriks@gmail.com Received: by 10.36.109.1 with SMTP id h1cs195536nzc; Tue, 7 Jun 2005 07:39:36 -0700 (PDT) Received: by 10.36.113.17 with SMTP id l17mr1524125nzc; Tue, 07 Jun 2005 07:37:56 -0700 (PDT) From: Mail Delivery Subsystem To: agris.ameriks@gmail.com Subject: Delivery Status Notification (Failure) Date: Tue, 07 Jun 2005 07:37:56 -0700 (PDT) This is an automatically generated Delivery Status Notification Delivery to the following recipient failed permanently: kasparsramins@gmail.com ----- Original message ----- Received: by 10.36.113.17 with SMTP id l17mr1248312nzc; Tue, 07 Jun 2005 07:37:56 -0700 (PDT) Received: by 10.36.109.1 with HTTP; Tue, 7 Jun 2005 07:37:55 -0700 (PDT) Message-ID: Date: Tue, 7 Jun 2005 17:37:55 +0300 From: Agris Ameriks Reply-To: Agris Ameriks To: Kaspars Ramins Subject: Fwd: You have received photos from Adobe Photoshop Elements In-Reply-To: <20050607143108.2A7FBD96C@epsilon.bkc.lv> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="----=_Part_21730_14622897.1118155075685" References: <20050607143108.2A7FBD96C@epsilon.bkc.lv> ------=_Part_21730_14622897.1118155075685 Content-Type: text/plain; charset=ISO-8859-13 Content-Transfer-Encoding: base64 Content-Disposition: inline LS0tLS0tLS0tLSBGb3J3YXJkZWQgbWVzc2FnZSAtLS0tLS0tLS0tCkZyb206IEFtZXJpWCA8YWdy aXNhQGFwb2xsby5sdj4KRGF0ZTogSnVuIDcsIDIwMDUgNTozMSBQTQpTdWJqZWN0OiBZb3UgaGF2 ZSByZWNlaXZlZCBwaG90b3MgZnJvbSBBZG9iZSBQaG90b3Nob3AgRWxlbWVudHMKVG86IEFncmlz LkFtZXJpa3NAZ21haWwuY29tCgoKIAogCgpSZWt1IGlyIGJpbGRlcyA7KSkpIAoKVGhlc2UgcGhv dG9zIHdlcmUgc2VudCBmcm9tIEFkb2JlKFIpIFBob3Rvc2hvcChSKSBFbGVtZW50cyAzLjAuIEZp bmQKb3V0IG1vcmU6IGh0dHA6Ly93d3cuYWRvYmUuY29tL3Bob3Rvc2hvcGVsZW1lbnRzd2luCgoK LS0gCkFyIGNpZfJ1LApBZ3JpcyBBbWVyaWtzClJTRCBLdWx0+3JhcyBrb21pdGVqYXMgdmFk7nTi anMKTW9iLnRlbC4gNjQ2MTEwMQpFLXBhc3RzOiBBZ3Jpcy5BbWVyaWtzQGdtYWlsLmNvbQo= ------=_Part_21730_14622897.1118155075685 Content-Type: image/jpeg; name=DSC04906.jpg Content-Transfer-Encoding: base64 Content-Disposition: attachment; filename="DSC04906.jpg" /9j/4UUoRXhpZgAASUkqAAgAAAAKAA8BAgAFAAAAhgAAABABAgAHAAAAjAAAABoBBQABAAAAlAAA ABsBBQABAAAAnAAAACgBAwABAAAAAgAAADEBAgAdAAAApAAAADIBAgAUAAAAwgAAABMCAwABAAAA AgAAAGmHBAABAAAA1gAAAKXEBwAcAAAAqAgAAMQIAABTT05ZAABEU0MtVDEAAOABAAAEAAAA4AEA AAQAAABBZG9iZSBQaG90b3Nob3AgRWxlbWVudHMgMy4wAAAyMDA1OjA2OjA3IDE3OjI5OjQyAB4A moIFAAEAAABEAgAAnYIFAAEAAABMAgAAIogDAAEAAAACAAAAJ4gDAAEAAABkAAAAAJAHAAQAAAAw MjIwA5ACABQAAABUAgAABJACABQAAABoAgAAAZEHAAQAAAABAgMAApEFAAEAAAB8AgAABJIKAAEA AACEAgAABZIFAAEAAACMAgAAB5IDAAEAAAAFAAAACJIDAAEAAAAAAAAACZIDAAEAAAANAAAACpIF AAEAAACUAgAAfJIHAO4FAACcAgAAAKAHAAQAAAAwMTAwAaADAAEAAAABAAAAAqAEAAEAAACAAgAA A6AEAAEAAADgAQAABaAEAAEAAACKCAAAAKMHAAEAAAADAAAAAaMHAAEAAAABAAAAAaQDAAEAAAAA AAAAAqQDAAEAAAAAAAAAA6QDAAEAAAAAAAAABqQDAAEAAAAAAAAACKQDAAEAAAAAAAAACaQDAAEA ----- Message truncated ----- schleuder-3.6.0/spec/fixtures/mails/bounces/tt_bounce_22.txt.eml000066400000000000000000000035061401002544500246450ustar00rootroot00000000000000Delivered-To: agris.ameriks@gmail.com Received: by 10.181.214.19 with SMTP id r19cs228343bkq; Thu, 22 Jan 2009 10:48:41 -0800 (PST) Received: by 10.181.36.9 with SMTP id o9mr1323719bkj.148.1232650120941; Thu, 22 Jan 2009 10:48:40 -0800 (PST) Return-Path: <> Received: by 10.181.36.9 with SMTP id o9mr1741352bkj.148; Thu, 22 Jan 2009 10:48:40 -0800 (PST) Message-ID: <001636c5b669974e1b046116b89e@googlemail.com> From: Mail Delivery Subsystem To: agris.ameriks@gmail.com Subject: Delivery Status Notification (Failure) Date: Thu, 22 Jan 2009 10:48:40 -0800 (PST) This is an automatically generated Delivery Status Notification Delivery to the following recipient failed permanently: flughafentransfer@loackertours.at Technical details of permanent failure: Google tried to deliver your message, but it was rejected by the recipient domain. We recommend contacting the other email provider for further information about the cause of this error. The error that the other server returned was: 550 550 Address unknown (state 14). ----- Original message ----- MIME-Version: 1.0 Received: by 10.181.36.9 with SMTP id o9mr1323494bkj.148.1232650074912; Thu, 22 Jan 2009 10:47:54 -0800 (PST) Date: Thu, 22 Jan 2009 20:47:54 +0200 Message-ID: Subject: Travel to Lech From: Agris Ameriks To: Agris.Ameriks@gmail.com Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 7bit Hello, we are going for spring holidays to Lech. We will be travelling to Zurich or to Munich by plane. We are going to arrive on 21th of March and we are going to travel back on 28th of March. We are 5 people. How much it will cost for us to travel from: x) Zurich to Lech and back ----- Message truncated ----- schleuder-3.6.0/spec/fixtures/mails/bounces/tt_bounce_23.txt.eml000066400000000000000000000152521401002544500246470ustar00rootroot00000000000000Delivered-To: agris.ameriks@gmail.com Received: by 10.66.241.15 with SMTP id o15cs81666ugh; Thu, 30 Aug 2007 01:16:11 -0700 (PDT) Received: by 10.86.76.16 with SMTP id y16mr222358fga.1188461771140; Thu, 30 Aug 2007 01:16:11 -0700 (PDT) Return-Path: <> Received: from pnew.exigengroup.lv (pnew.exigengroup.lv [80.233.156.204]) by mx.google.com with ESMTP id d13si451649fka.2007.08.30.01.16.09; Thu, 30 Aug 2007 01:16:11 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of pnew.exigengroup.lv designates 80.233.156.204 as permitted sender) client-ip=80.233.156.204; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of pnew.exigengroup.lv designates 80.233.156.204 as permitted sender) smtp.mail= Received: from localhost (localhost) by pnew.exigengroup.lv (X.VV.Z/X.VV.Z) id l7U8G8X9006653; Thu, 30 Aug 2007 11:16:08 +0300 Date: Thu, 30 Aug 2007 11:16:08 +0300 From: Mail Delivery Subsystem Message-Id: <200708300816.l7U8G8X9006653@pnew.exigengroup.lv> To: MIME-Version: 1.0 Content-Type: multipart/report; report-type=delivery-status; boundary="l7U8G8X9006653.1188461768/pnew.exigengroup.lv" Subject: Returned mail: see transcript for details Auto-Submitted: auto-generated (failure) This is a MIME-encapsulated message --l7U8G8X9006653.1188461768/pnew.exigengroup.lv The original message was received at Thu, 30 Aug 2007 11:16:05 +0300 from lnrixm01.exigengroup.lv [192.168.0.115] ----- The following addresses had permanent fatal errors ----- (reason: 550 Rihards_Freimanis@exigengroup.com... No such user) ----- Transcript of session follows ----- ... while talking to lnsfoh01.exigengroup.com.: >>> DATA <<< 550 Rihards_Freimanis@exigengroup.com... No such user 550 5.1.1 ... User unknown <<< 503 Issue RCPT TO: command before DATA command --l7U8G8X9006653.1188461768/pnew.exigengroup.lv Content-Type: message/delivery-status Reporting-MTA: dns; pnew.exigengroup.lv Received-From-MTA: DNS; lnrixm01.exigengroup.lv Arrival-Date: Thu, 30 Aug 2007 11:16:05 +0300 Final-Recipient: RFC822; Rihards_Freimanis@exigengroup.com Action: failed Status: 5.1.1 Remote-MTA: DNS; lnsfoh01.exigengroup.com Diagnostic-Code: SMTP; 550 Rihards_Freimanis@exigengroup.com... No such user Last-Attempt-Date: Thu, 30 Aug 2007 11:16:08 +0300 --l7U8G8X9006653.1188461768/pnew.exigengroup.lv Content-Type: message/rfc822 Return-Path: Received: from lnrixm01.exigengroup.lv (lnrixm01.exigengroup.lv [192.168.0.115]) by pnew.exigengroup.lv (X.VV.Z/X.VV.Z) with ESMTP id l7U8G5X9006650 for ; Thu, 30 Aug 2007 11:16:05 +0300 Received: from riskynew.exigengroup.lv ([192.168.0.4]) by lnrixm01.exigengroup.lv (Lotus Domino Release 6.5.5FP2) with ESMTP id 2007083011160393-377644 ; Thu, 30 Aug 2007 11:16:03 +0300 Received: from nf-out-0910.google.com (nf-out-0910.google.com [64.233.182.190]) by riskynew.exigengroup.lv (X.VV.Z/X.VV.Z) with ESMTP id l7U8MA3M025009 for ; Thu, 30 Aug 2007 11:22:10 +0300 Received: by nf-out-0910.google.com with SMTP id 4so1127851nfv for ; Thu, 30 Aug 2007 01:16:01 -0700 (PDT) DKIM-Signature: a=rsa-sha1; c=relaxed/relaxed; d=gmail.com; s=beta; h=domainkey-signature:received:received:message-id:date:from:to:subject:cc:mime-version:content-type; b=rAsdg7B2GKZQMXP9hebb2Ht3x+R4VFR8jCk292KnlSm0mlq+ARoT/lGZaBfxvK01Wf/8yGIJyuz049Khs3hNwGSpQyNUQs8fJNPRjgmi7DndbsSKxPylKkaKp6l68WAeEcH9KqxDuCpFiQ81X4WxapI0WUlZ2gNqnqtEnh5Fyno= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=beta; h=received:message-id:date:from:to:subject:cc:mime-version:content-type; b=s+jOmEvmEw7nKfTq9rj4kz6LP/oJlr4OhLO5MWWerf1EhjJ2k2RLDS1qkXKkIPpdOo5DNb2FKbWXIT/95aW7vRwmLLR9oSFCjrvS9Tnwwi7EgX2ek8VSHvbDwFxfQ3sH+dcjFEKa3uxG9Xv7bZUijYVW4WPKofFkwYeKetGXs9w= Received: by 10.78.134.2 with SMTP id h2mr72227hud.1188461760745; Thu, 30 Aug 2007 01:16:00 -0700 (PDT) Received: by 10.66.241.15 with HTTP; Thu, 30 Aug 2007 01:16:00 -0700 (PDT) Message-ID: Date: Thu, 30 Aug 2007 11:16:00 +0300 From: "Agris Ameriks" To: rihards_freimanis@exigengroup.lv Subject: =?ISO-8859-13?Q?Iel=FBgums_studentu_korpor=E2cijai?= Cc: "=?ISO-8859-13?Q?J=E2nis_Erts?=" , "Edgars Gutkis" MIME-Version: 1.0 X-MIMETrack: Itemize by SMTP Server on LNRIXM01/Eur/Srv/Exigen(Release 6.5.5FP2|October 23, 2006) at 08/30/2007 11:16:04 AM, Serialize by Router on LNRIXM01/Eur/Srv/Exigen(Release 6.5.5FP2|October 23, 2006) at 08/30/2007 11:16:06 AM Content-Type: multipart/mixed; boundary="----=_Part_5343_11195373.1188461760389" ------=_Part_5343_11195373.1188461760389 Content-Transfer-Encoding: base64 Content-Type: text/plain; charset=ISO-8859-13 Content-Disposition: inline TGFiZGllbiEKCkllbPtkemFtIEr7cyBwaWVkYWzudGllcyB1biBwcmV6ZW5053Qgc2V2aSBTdHVk ZW50IFBhcnR5IHBhc+JrdW1hCmlldHZhcm9zIDE1LnNlcHRlbWJy7iBFc3BsYW7iZOcgbm8gcGxr c3QuIDE1OjAwIC0gMTk6MDAuCgpQcmV6ZW5053Qgc2V2aSBK+3MgdmFy53NpZXQgSvtzdSB1enN0 4mTudOIgdGVsdO4sIG37c3UgaWVy4mTudOIgdmlldOIuCgpM+2R6dSBpZXBheu5zdGlldGllcyBh ciBwcm9qZWt0dSB1biBpbmZvcm3namlldCBt+3MgcGFyIEr7c3UgZGFs7mJ1CnDnYyBpZXNw52ph cyDidHLiay4KCk11bXMgYvtzIG5lcGllY2ll8GFtYSBhcu4gSvtzdSB0ZWx0cyBwcm9ncmFtbWEu CgpUZWx0cyBq4mfiZOIgcGHwaWVtLgoKS29udGFrdOdqaWV0aWVzIGFyIEVkZ2FydSBHdXRraSBl ZGdhcnMuZ3V0a2lzQGdtYWlsLmNvbSAyOTg2NTA0Ni4KCgpQaWVsaWt1beI6CnByb2pla3RzCgpQ LlMuIEphIEr7cyB6aW7idCBr4mR1IG9yZ2FuaXriY2lqdSwga3VyYSBi+3R1IGricHJlemVudOcg c3R1ZGVudGllbQp1biBrdXJhLCBpZXNw52phbXMsIGL7dHUgZ2F0YXZhIHByZXplbnTndCBzZXZp LCBkb2RhdCB6aW7idC4KCi0tCkFyIGNpZfJ1LApBZ3JpcyBBbWVyaWtzCk1vYi50ZWwuIDIgNjQ2 MTEwMQpFLXBhc3RzOiBBZ3Jpcy5BbWVyaWtzQGdtYWlsLmNvbQo= ------=_Part_5343_11195373.1188461760389 X-Attachment-Id: f_f5yza5p5 Content-Type: application/msword; name="PROJEKTS V3_2_bez.doc" Content-Disposition: attachment; filename="PROJEKTS V3_2_bez.doc"; filename="PROJEKTS V3_2_bez.doc"; filename="PROJEKTS V3_2_bez.doc"; filename="PROJEKTS V3_2_bez.doc" Content-Transfer-Encoding: base64 0M8R4KGxGuEAAAAAAAAAAAAAAAAAAAAAPgADAP7/CQAGAAAAAAAAAAAAAAAFAAAAKgIAAAAAAAAA EAAALQIAAAEAAAD+////AAAAACUCAAAmAgAAJwIAACgCAAApAgAA//////////////////////// //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// AAAAAAAAAAAAAttachmentTruncated ------=_Part_5343_11195373.1188461760389-- --l7U8G8X9006653.1188461768/pnew.exigengroup.lv-- schleuder-3.6.0/spec/fixtures/mails/bounces/tt_bounce_24.txt.eml000066400000000000000000000303411401002544500246440ustar00rootroot00000000000000Return-Path: <> Delivered-To: badmail@testcompany.se Received: (qmail 2967 invoked from network); 26 Apr 2011 14:27:59 -0000 Received: from mx1.forss.net ([95.128.113.140]) (envelope-sender <>) by mail1.forss.net (qmail-ldap-1.03) with AES256-SHA encrypted SMTP for ; 26 Apr 2011 14:27:59 -0000 Received: from localhost (localhost [127.0.0.1]) by mx1.forss.net (Postfix) with ESMTP id 62B5A380087CF for ; Tue, 26 Apr 2011 16:27:59 +0200 (CEST) X-Virus-Scanned: Forss Webservice Scanner at forss.net X-Spam-Flag: NO X-Spam-Score: -1.427 X-Spam-Level: X-Spam-Status: No, score=-1.427 tagged_above=-1000 required=4 tests=[BAYES_00=-2.599, HTML_MESSAGE=0.001, MIME_BOUND_MANY_HEX=0.803, URI_HEX=0.368] Received: from customer-relay.songnetworks.se (customer-relay.songnetworks.se [195.42.210.9]) by mx1.forss.net (Postfix) with ESMTP id 7059D3800560E for ; Tue, 26 Apr 2011 16:27:57 +0200 (CEST) Received: from mail.test-receive-domain.se (mail.test-receive-domain.se [213.88.128.20]) by customer-relay.songnetworks.se (Postfix) with ESMTP id 9FEA624388 for ; Tue, 26 Apr 2011 16:27:56 +0200 (CEST) MIME-Version: 1.0 From: To: Date: Tue, 26 Apr 2011 16:27:48 +0200 Content-Type: multipart/report; report-type=delivery-status; boundary="f518d4c6-edf1-4463-b115-f1a617b52ef3" Content-Language: sv-SE Message-ID: <271e9eed-2188-497a-b051-53ad11a74673@test-receive-domain.se> In-Reply-To: <4db6d64e2f07a_1009115d44c424c@linux1.mail> References: <4db6d64e2f07a_1009115d44c424c@linux1.mail> Subject: =?iso-8859-1?Q?Olevererbart::_Testcompany_-_bekr=E4ftelse_byte_av_levera?= =?iso-8859-1?Q?nt=F6r?= --f518d4c6-edf1-4463-b115-f1a617b52ef3 Content-Type: multipart/alternative; differences=Content-Type; boundary="6377eb29-66bb-46fd-90f3-d8c649abf8d2" --6377eb29-66bb-46fd-90f3-d8c649abf8d2 Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: quoted-printable Det gick inte att leverera till f=F6ljande mottagare eller grupper: customer.testemail@test-receive-domain.se Det gick inte att hitta e-postadressen du angav. Kontrollera adressen och f= =F6rs=F6k sedan skicka meddelandet igen. Kontakta din supportavdelning om p= roblemet kvarst=E5r. Diagnostisk information f=F6r administrat=F6rer: Genererande server: test-receive-domain.se customer.testemail@test-receive-domain.se #550 5.1.1 RESOLVER.ADR.RecipNotFound; not found ## Ursprungshuvuden: Received: from p02c12m081.mxlogic.net (208.65.145.245) by fgsrv-mail01.fasadglas.sto (192.168.0.8) with Microsoft SMTP Server id 14.0.722.0; Tue, 26 Apr 2011 16:27:47 +0200 Received: from unknown [95.128.113.150] (EHLO mail1.forss.net) by p02c12m081.mxlogic.net(mxl_mta-6.9.0-2) over TLS secured channel wit= h ESMTP id 566d6bd4.0.3897208.00-2256.4580924.p02c12m081.mxlogic.net (envelope-fro= m ); Tue, 26 Apr 2011 08:27:51 -0600 (MDT) Received: (qmail 487 invoked from network); 26 Apr 2011 14:27:28 -0000 X-Mail-System: Forss Webservice AB Mailsystem (www.forss.se) X-Virus-Scanner: Panda CommandLine Secure for Linux X-Virus-Status: No virus found X-Spam-Checker-Version: SpamAssassin 3.1.0 (2005-09-13) on mail2.forss.net X-Spam-Level: X-Spam-Status: No, score=3D-3.4 required=3D5.0 tests=3DALL_TRUSTED,AWL,BAYE= S_00, HTML_30_40,HTML_MESSAGE,MIME_HTML_ONLY autolearn=3Dham version=3D3.= 1.0 Received: from n-95-128-115-31.net.forss.net (HELO server1.testcompany.se) (application@testcompany.com@[95.128.115.31]) (envelope-sender ) by mail1.forss.net (qmail-ldap-1.03) with SMTP for ; 26 Apr 2011 14:27:26 -000= 0 Received: by server1.testcompany.se (Postfix, from userid 1001) id 3DD205F6= 7A; Tue, 26 Apr 2011 16:27:26 +0200 (CEST) Date: Tue, 26 Apr 2011 16:27:26 +0200 From: Testcompany To: Message-ID: <4db6d64e2f07a_1009115d44c424c@linux1.mail> Subject: =3D?UTF-8?Q?Testcompany_-_bekr=3DC3=3DA4ftelse_byte_av_leverant= =3DC3=3DB6r?=3D MIME-Version: 1.0 Content-Type: text/html; charset=3D"UTF-8" Content-Transfer-Encoding: quoted-printable X-BS-Tracker: 14771 X-BS-Id: 13362 X-Processed-By: Rebuild v2.0-0 X-Spam: [F=3D0.1428571429; B=3D0.500(0); STSI=3D0.500(-12); STSM=3D0.400(-1= 2); CM=3D0.500; MH=3D0.500(2011042613); S=3D0.200(2010122901); SC=3Dnone] X-MAIL-FROM: X-SOURCE-IP: [95.128.113.150] X-AnalysisOut: [v=3D1.0 c=3D1 a=3D_5SL2JS5Q28A:10 a=3DjPJDawAOAc8A:10 a=3DB= LceEmwcHo] X-AnalysisOut: [wA:10 a=3DIkcTkHD0fZMA:10 a=3D8JvCOHtooGmM4q1c5eVAlw=3D=3D:= 17 a=3D3G] X-AnalysisOut: [eILzi6AAAA:8 a=3DiwwpTHDTvyZOjFydv4QA:9 a=3DPf0nvSi-hewE5oC= hIv] X-AnalysisOut: [oA:7 a=3DQEXdDO2ut3YA:10] Return-Path: badmail@testcompany.se --6377eb29-66bb-46fd-90f3-d8c649abf8d2 Content-Type: text/html; charset="iso-8859-1" Content-Transfer-Encoding: quoted-printable

Det gick inte att l= everera till f=F6ljande mottagare eller grupper:

customer.testemail@test-receive-domain.se
Det gick inte att hitta e-postadressen du angav. Kontrollera adressen och f= =F6rs=F6k sedan skicka meddelandet igen. Kontakta din supportavdelning om p= roblemet kvarst=E5r.







Diagnostisk inform= ation f=F6r administrat=F6rer:

Genererande server: test-receive-domain.se

customer.testemail@test-receive-domain.se
#550 5.1.1 RESOLVER.ADR.RecipNotFound; not found ##

Ursprungshuvuden:

Received: from p02c12m081.mxlogic.net (208.65.145.245) by
 fgsrv-mail01.fasadglas.sto (192.168.0.8) with Microsoft SMTP Server id
 14.0.722.0; Tue, 26 Apr 2011 16:27:47 +0200
Received: from unknown [95.128.113.150] (EHLO mail1.forss.net)	by
 p02c12m081.mxlogic.net(mxl_mta-6.9.0-2) over TLS secured channel	with ESMT=
P
 id 566d6bd4.0.3897208.00-2256.4580924.p02c12m081.mxlogic.net (envelope-fro=
m
 <badmail@testcompany.se>);	Tue, 26 Apr 2011 08:27:51 -0600 (MDT)
Received: (qmail 487 invoked from network); 26 Apr 2011 14:27:28 -0000
X-Mail-System: Forss Webservice AB Mailsystem (www.forss.se)
X-Virus-Scanner: Panda CommandLine Secure for Linux
X-Virus-Status: No virus found
X-Spam-Checker-Version: SpamAssassin 3.1.0 (2005-09-13) on mail2.forss.net
X-Spam-Level:
X-Spam-Status: No, score=3D-3.4 required=3D5.0 tests=3DALL_TRUSTED,AWL,BAYE=
S_00,
	HTML_30_40,HTML_MESSAGE,MIME_HTML_ONLY autolearn=3Dham version=3D3.1.0
Received: from n-95-128-115-31.net.forss.net (HELO server1.testcompany.se)
 (application@testcompany.com@[95.128.115.31])          (envelope-sender
 <badmail@testcompany.se>)          by mail1.forss.net (qmail-ldap-1.03=
) with
 SMTP          for <customer.testemail@test-receive-domain.se>; 26 Apr 2011 14:27:2=
6 -0000
Received: by server1.testcompany.se (Postfix, from userid 1001)	id 3DD205F67=
A;
 Tue, 26 Apr 2011 16:27:26 +0200 (CEST)
Date: Tue, 26 Apr 2011 16:27:26 +0200
From: Testcompany <info@testcompany.se>
To: <customer.testemail@test-receive-domain.se>
Message-ID: <4db6d64e2f07a_1009115d44c424c@linux1.mail>
Subject: =3D?UTF-8?Q?Testcompany_-_bekr=3DC3=3DA4ftelse_byte_av_leverant=
=3DC3=3DB6r?=3D
MIME-Version: 1.0
Content-Type: text/html; charset=3D"UTF-8"
Content-Transfer-Encoding: quoted-printable
X-BS-Tracker: 14771
X-BS-Id: 13362
X-Processed-By: Rebuild v2.0-0
X-Spam: [F=3D0.1428571429; B=3D0.500(0); STSI=3D0.500(-12); STSM=3D0.400(-1=
2); CM=3D0.500; MH=3D0.500(2011042613); S=3D0.200(2010122901); SC=3Dnone]
X-MAIL-FROM: <badmail@testcompany.se>
X-SOURCE-IP: [95.128.113.150]
X-AnalysisOut: [v=3D1.0 c=3D1 a=3D_5SL2JS5Q28A:10 a=3DjPJDawAOAc8A:10 a=3DB=
LceEmwcHo]
X-AnalysisOut: [wA:10 a=3DIkcTkHD0fZMA:10 a=3D8JvCOHtooGmM4q1c5eVAlw=3D=3D:=
17 a=3D3G]
X-AnalysisOut: [eILzi6AAAA:8 a=3DiwwpTHDTvyZOjFydv4QA:9 a=3DPf0nvSi-hewE5oC=
hIv]
X-AnalysisOut: [oA:7 a=3DQEXdDO2ut3YA:10]
Return-Path: badmail@testcompany.se

= --6377eb29-66bb-46fd-90f3-d8c649abf8d2-- --f518d4c6-edf1-4463-b115-f1a617b52ef3 Content-Type: message/delivery-status Reporting-MTA: dns;test-receive-domain.se Received-From-MTA: dns;p02c12m081.mxlogic.net Arrival-Date: Tue, 26 Apr 2011 14:27:47 +0000 Final-Recipient: rfc822;customer.testemail@test-receive-domain.se Action: failed Status: 5.1.1 Diagnostic-Code: smtp;550 5.1.1 RESOLVER.ADR.RecipNotFound; not found --f518d4c6-edf1-4463-b115-f1a617b52ef3 Content-Type: message/rfc822 Received: from p02c12m081.mxlogic.net (208.65.145.245) by fgsrv-mail01.fasadglas.sto (192.168.0.8) with Microsoft SMTP Server id 14.0.722.0; Tue, 26 Apr 2011 16:27:47 +0200 Received: from unknown [95.128.113.150] (EHLO mail1.forss.net) by p02c12m081.mxlogic.net(mxl_mta-6.9.0-2) over TLS secured channel with ESMTP id 566d6bd4.0.3897208.00-2256.4580924.p02c12m081.mxlogic.net (envelope-from ); Tue, 26 Apr 2011 08:27:51 -0600 (MDT) Received: (qmail 487 invoked from network); 26 Apr 2011 14:27:28 -0000 X-Mail-System: Forss Webservice AB Mailsystem (www.forss.se) X-Virus-Scanner: Panda CommandLine Secure for Linux X-Virus-Status: No virus found X-Spam-Checker-Version: SpamAssassin 3.1.0 (2005-09-13) on mail2.forss.net X-Spam-Level: X-Spam-Status: No, score=-3.4 required=5.0 tests=ALL_TRUSTED,AWL,BAYES_00, HTML_30_40,HTML_MESSAGE,MIME_HTML_ONLY autolearn=ham version=3.1.0 Received: from n-95-128-115-31.net.forss.net (HELO server1.testcompany.se) (application@testcompany.com@[95.128.115.31]) (envelope-sender ) by mail1.forss.net (qmail-ldap-1.03) with SMTP for ; 26 Apr 2011 14:27:26 -0000 Received: by server1.testcompany.se (Postfix, from userid 1001) id 3DD205F67A; Tue, 26 Apr 2011 16:27:26 +0200 (CEST) Date: Tue, 26 Apr 2011 16:27:26 +0200 From: Testcompany To: Message-ID: <4db6d64e2f07a_1009115d44c424c@linux1.mail> Subject: =?UTF-8?Q?Testcompany_-_bekr=C3=A4ftelse_byte_av_leverant=C3=B6r?= MIME-Version: 1.0 Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable X-BS-Tracker: 14771 X-BS-Id: 13362 X-Processed-By: Rebuild v2.0-0 X-Spam: [F=0.1428571429; B=0.500(0); STSI=0.500(-12); STSM=0.400(-12); CM=0.500; MH=0.500(2011042613); S=0.200(2010122901); SC=none] X-MAIL-FROM: X-SOURCE-IP: [95.128.113.150] X-AnalysisOut: [v=1.0 c=1 a=_5SL2JS5Q28A:10 a=jPJDawAOAc8A:10 a=BLceEmwcHo] X-AnalysisOut: [wA:10 a=IkcTkHD0fZMA:10 a=8JvCOHtooGmM4q1c5eVAlw==:17 a=3G] X-AnalysisOut: [eILzi6AAAA:8 a=iwwpTHDTvyZOjFydv4QA:9 a=Pf0nvSi-hewE5oChIv] X-AnalysisOut: [oA:7 a=QEXdDO2ut3YA:10] Return-Path: badmail@testcompany.se TestCompany =20
=20 Hej Test,
Test Comapny AB vill informera dig om att vi har sett =C3=B6ver ditt avtal oc= h funnit en besparingspotential i att byta ditt avtal till=20 service provider varf=C3=B6r vi kommer att genomf=C3=B6ra detta byte i enlighet med = den fullmakt du givit oss. Test Company AB genomf=C3=B6r detta bytet i sin str=C3= =A4van att minimera dina kostnader och kontinuerligt erbjuda dig som medlem= l=C3=A4gsta m=C3=B6jliga pris.

Med v=C3=A4nlig h=C3=A4lsning

Test Company Sweden AB
Tj=C3=A4stvägen 21 A
100 10 Stockholm
=20 --f518d4c6-edf1-4463-b115-f1a617b52ef3-- schleuder-3.6.0/spec/fixtures/mails/bounces/tt_bounce_25.txt.eml000066400000000000000000000051741401002544500246530ustar00rootroot00000000000000Return-Path: <> Delivered-To: badmail@test-domain.se Received: (qmail 23861 invoked for bounce); 14 Apr 2011 15:44:12 -0000 Date: 14 Apr 2011 15:44:12 -0000 From: MAILER-DAEMON@mail1.forss.net To: badmail@test-domain.se Subject: failure notice Hi. This is the qmail-send program at mail1.forss.net. I'm afraid I wasn't able to deliver your message to the following addresses. This is a permanent error; I've given up. Sorry it didn't work out. : 65.55.37.120 does not like recipient. Remote host said: 550 Requested action not taken: mailbox unavailable Giving up on 65.55.37.120. --- Below this line is a copy of the message. Return-Path: Received: (qmail 23836 invoked from network); 14 Apr 2011 15:44:11 -0000 X-Mail-System: Forss Webservice AB Mailsystem (www.forss.se) X-Virus-Scanner: Panda CommandLine Secure for Linux X-Virus-Status: No virus found X-Spam-Checker-Version: SpamAssassin 3.1.0 (2005-09-13) on mail2.forss.net X-Spam-Level: X-Spam-Status: No, score=-3.3 required=5.0 tests=ALL_TRUSTED,AWL,BAYES_00, HTML_30_40,HTML_MESSAGE,MIME_HTML_ONLY autolearn=ham version=3.1.0 Received: from n-95-128-115-31.net.forss.net (HELO server1.test-domain.com) (application@test-domain.com@[95.115.100.31]) (envelope-sender ) by mail1.forss.net (qmail-ldap-1.03) with SMTP for ; 14 Apr 2011 15:44:11 -0000 Received: by server1.test-domain.com (Postfix, from userid 1001) id DEA9112988A; Thu, 14 Apr 2011 17:44:10 +0200 (CEST) Date: Thu, 14 Apr 2011 17:44:10 +0200 From: TestCompany To: Delar-Med-Frun@live.se Message-ID: <4da7164ad9229_c19a7f9f495573@linux1.mail> Subject: =?UTF-8?Q?TestCompany_-_V=C3=A4lkommen_som_medlem?= Mime-Version: 1.0 Content-Type: text/html; charset=UTF-8 Content-Transfer-Encoding: quoted-printable TestCompany
V=C3=A4lkomme= n som medlem i Baraspara
Hej Test,
Vi tackar f=C3=B6r ett trevligt samtal och =C3=B6nskar dig varmt v=C3=A4l= kommen som medlem i TestCompany. =
=schleuder-3.6.0/spec/fixtures/mails/bounces/undeliverable_gmail.txt.eml000066400000000000000000000102661401002544500263530ustar00rootroot00000000000000 Delivered-To: saghaulor@gmail.com Received: by 10.96.89.195 with SMTP id bq3csp193052qdb; Wed, 25 Mar 2015 16:06:37 -0700 (PDT) X-Received: by 10.236.231.244 with SMTP id l110mr3446122yhq.76.1427324797301; Wed, 25 Mar 2015 16:06:37 -0700 (PDT) Return-Path: <> Received: from mail-yk0-x246.google.com (mail-yk0-x246.google.com. [2607:f8b0:4002:c07::246]) by mx.google.com with ESMTPS id v10si1943530yhn.71.2015.03.25.16.06.37 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 25 Mar 2015 16:06:37 -0700 (PDT) Received-SPF: none (google.com: mail-yk0-x246.google.com does not designate permitted sender hosts) client-ip=2607:f8b0:4002:c07::246; Authentication-Results: mx.google.com; spf=none (google.com: mail-yk0-x246.google.com does not designate permitted sender hosts) smtp.mail=; dkim=pass header.i=@googlemail.com Received: by mail-yk0-x246.google.com with SMTP id u21so9169ykd.2 for ; Wed, 25 Mar 2015 16:06:37 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=googlemail.com; s=20120113; h=mime-version:from:to:subject:message-id:date:content-type; bh=zDroqkBtnjOx4oQsUjOsgCFXb0x6mWh6blclcKQ5iYI=; b=PXS6yid56wdSx7roUQJoBggDMdNZT8cIIv5WQYV5IN4O/Vna8giENzEBwTsMyEPHBo JfVgmhO6VWJ4RFjprNQdwHtBgU6XCmGKyK7pfQmmjyukMv+goACB/ApUnmDKgzV/QzuB 3yAwRnPN4srOivQXM9l5TA5OUzoIS9rDGA+bg229WXSqU+xbsUE1hj1iCsL+1gsEqWMi m0Vpo9putaSS2Xz0SmJFq8biRKXbinBSb5d33kDp8T9P5GkRPD15byuXEKIrwR/81wXn miucJ+GuMV5Y/g7N49Nz51H6nQgG0P3VBMuQxLrNBQPb7ofnh09hsW6PwlEu0Ba2LHkS 0A3w== X-Received: by 10.140.144.11 with SMTP id 11mr14639966qhq.54.1427324797247; Wed, 25 Mar 2015 16:06:37 -0700 (PDT) MIME-Version: 1.0 Return-Path: <> Received: by 10.140.144.11 with SMTP id 11mr12478298qhq.54; Wed, 25 Mar 2015 16:06:37 -0700 (PDT) From: Mail Delivery Subsystem To: saghaulor@gmail.com X-Failed-Recipients: undeliverable@coupa.com Subject: Delivery Status Notification (Failure) Message-ID: <001a1137654084e059051224f354@google.com> Date: Wed, 25 Mar 2015 23:06:37 +0000 Content-Type: text/plain; charset=UTF-8 Delivery to the following recipient failed permanently: undeliverable@coupa.com Technical details of permanent failure: Google tried to deliver your message, but it was rejected by the server for the recipient domain coupa.com by aspmx.l.google.com. [2607:f8b0:400d:c03::1b]. The error that the other server returned was: 550-5.1.1 The email account that you tried to reach does not exist. Please try 550-5.1.1 double-checking the recipient's email address for typos or 550-5.1.1 unnecessary spaces. Learn more at 550 5.1.1 http://support.google.com/mail/bin/answer.py?answer=6596 140si3605502qhd.80 - gsmtp ----- Original message ----- DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=mime-version:from:date:message-id:subject:to:content-type; bh=EeOLB+iPfnulBvl+QlMunNfssBotsqV19IRSrGZ7wjE=; b=cZHw/hf4sqwgBCotRSuBGMcyEViNc9PIYhV/1wVrmYZYcXsleL0b2laAQD3ri5WO67 cLQc2a2tfTRfDFTiq1JQ9MOmcRatUUBmbkydjOq8R8Xqf4bi6wJobZL0ieiT/CHJtQuk MLF/UkM10Ev/FBHFZSBnowZDhEjUzVRO4aRDHyPjzPS3+456c3ywuvb0nVDphKKMTrNW FDyaYlG01XgkgPaguknjOVpK59cSJ/aQyLBW9EoQBEgOPtkzhXbVBbiM+7ofL6DXi7lm UnMFYUkzKPnDoVlqD0d+ykjrun3a2gLD6aNXKQDynTmRpWvdzCRwsoC5UkflU5D4303U +9HQ== X-Received: by 10.140.144.11 with SMTP id 11mr14639959qhq.54.1427324797130; Wed, 25 Mar 2015 16:06:37 -0700 (PDT) MIME-Version: 1.0 From: Stephen Aghaulor Date: Wed, 25 Mar 2015 23:06:36 +0000 Message-ID: Subject: Test To: undeliverable@coupa.com Content-Type: multipart/alternative; boundary=001a1137654083206f051224f3e9 Test schleuder-3.6.0/spec/fixtures/mails/bounces/unknown_code_bounce_01.txt.eml000066400000000000000000000054461401002544500267110ustar00rootroot00000000000000Return-Path: <> Received: by 10.231.11.4 with SMTP id r4cs16374ibr; Sun, 31 Jan 2010 21:45:58 +0000 Date: Sun, 31 Jan 2010 21:45:57 +0000 From: Postmaster@tradingpost.ch To: jack@swom.com Message-Id: <4b65fa15.160db80a.5b82.ffff9cedSMTPIN_ADDED@mx.google.com> Subject: Mail Delivery Failure X-Loop-Detect: 4 Final-Recipient: rfc822;sdrake@tradingpost.ch Authentication-Results: mx.google.com; spf=pass (google.com: domain of mail03c.hostcenter.com designates 195.186.64.158 as permitted sender) smtp.mail= Delivered-To: jack@swom.com Original-Recipient: rfc822;sdrake@tradingpost.ch Received-Spf: pass (google.com: domain of mail03c.hostcenter.com designates 195.186.64.158 as permitted sender) client-ip=195.186.64.158; Delivery of email to this address "sdrake@tradingpost.ch" has failed due to a full mailbox. We have already made numerous attempts to deliver this message over the last few days. Please try to send your message again at a later time. The first 50 lines of your original message follow:> Received: from mx21.stngva01.us.mxservers.net (204.202.242.71) > by mail03c-old.hostcenter.com (RS ver 1.0.95vs) with SMTP id 4-033563664 > for ; Sun, 31 Jan 2010 02:17:45 +0100 (CET) > Received: from unknown [188.40.35.30] (EHLO xenon.swom.com) > by va1-mx21.stngva01.us.mxservers.net (mxl_mta-3.1.0-05) > with ESMTP id 73ad46b4.2654722976.745535.00-003.va1-mx21.stngva01.us.mxservers.net (envelope-from ); > Sat, 30 Jan 2010 20:17:43 -0500 (EST) > Received: from myswom.com (xenon.swom.com [188.40.35.28]) > (Authenticated sender: support@myswom.com) > by xenon.swom.com (Postfix) with ESMTPSA id 979FE3D27 > for ; Sun, 31 Jan 2010 01:16:45 +0000 (GMT) > Date: Sun, 31 Jan 2010 01:16:45 +0000 > From: Jack Whitehall > To: sdrake@tradingpost.ch > Message-Id: <4b64d9fd8f537_18e83fa070dbb1b85499c1@xenon.swom.com.tmail> > Subject: From Jack Whitehall > Mime-Version: 1.0 > Content-Type: text/plain; charset=utf-8 > X-Swom-Uuid: 257c92310bd354f1cd0f2ca4e5fd75fe50f68355 > X-Spam: [F=0.2000000000; B=0.500(0); S=0.200(2010011101); MH=0.500(2010013027)] > X-MAIL-FROM: > X-SOURCE-IP: [188.40.35.30] > X-Loop-Detect:1 > X-DistLoop-Detect:1 > > Hi Simon - Hide quoted text - > > Jack Whitehall here, co-founder of the old CashCulture program in 2003. I thought I'd reconnect with my contacts. > > So what are you up to nowadays? > > I'm working on Swom.com, a lucrative program which is very cool! Its payplan gives earnings of $10k/month. > > I've got a special VIP pre-launch link before it goes on international launch to millions on Mar 1st. If you use the link you'll get a ton of spillover. > > http://swom.com/r/34118 > > Do write back - be great to hear from you after all these years. > > = Jackschleuder-3.6.0/spec/fixtures/mails/broken_utf8_charset.eml000066400000000000000000000032701401002544500240410ustar00rootroot00000000000000Return-Path: Delivered-To: example@example.org Received: from mail.example.org (mail.example.org [192.168.1.2]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by trebuchet.example.org (Postfix) with ESMTPS id 2C8A1A0403 for ; Sat, 10 Mar 2018 02:52:58 +0100 (CET) Received: from [127.0.0.1] (localhost [127.0.0.1])example.org (mx.example.org [192.168.1.1]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.example.org (Postfix) with ESMTPS id 7FB4610F for ; Sat, 10 Mar 2018 02:52:57 +0100 (CET) Received: from [127.0.0.1] (localhost [127.0.0.1])ng TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx2.example.org (Postfix) with ESMTPS id DA6D2880A0 for ; Sat, 10 Mar 2018 02:52:54 +0100 (CET) Received: from [127.0.0.1] (localhost [127.0.0.1])novol420-pc (unknown [192.168.1.3]) by smtp1-g21.free.fr (Postfix) with SMTP id 95E05B0051B for ; Sat, 10 Mar 2018 02:52:51 +0100 (CET) Message-ID: From: "Invitation" To: Subject: =?windows-1258?B?c29pcull?= Date: Sat, 10 Mar 2018 02:52:36 +0100 MIME-Version: 1.0 Content-Type: multipart/alternative; boundary="----=MailPart0000_0010_0A37C499" This is a multi-part message in MIME format. ------=MailPart0000_0010_0A37C499 Content-Type: text/plain; charset="windows-1258" Content-Transfer-Encoding: quoted-printable Hello Goodbye ------=MailPart0000_0010_0A37C499-- schleuder-3.6.0/spec/fixtures/mails/charset_mails/000077500000000000000000000000001401002544500222175ustar00rootroot00000000000000schleuder-3.6.0/spec/fixtures/mails/charset_mails/japanese.eml000066400000000000000000000005011401002544500245000ustar00rootroot00000000000000MIME-Version: 1.0 Subject: =?UTF-8?B?44G+44G/44KA44KB44KC?= From: sender@example.com To: =?UTF-8?B?44G/44GR44KL?= Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: base64 44GL44GN44GP44GI44GTCgotLSAKaHR0cDovL2xpbmRzYWFyLm5ldC8KUmFpbHMsIFJTcGVjIGFu ZCBMaWZlIGJsb2cuLi4uCg==schleuder-3.6.0/spec/fixtures/mails/charset_mails/japanese_attachment.eml000066400000000000000000000015641401002544500267220ustar00rootroot00000000000000MIME-Version: 1.0 Received: by 10.231.35.72 with HTTP; Fri, 16 Oct 2009 05:39:34 -0700 (PDT) Date: Fri, 16 Oct 2009 23:39:34 +1100 Delivered-To: schleuder@example.org Message-ID: <57a815bf0910160539m64240421gb35ea52e101aedbc@mail.gmail.com> Subject: testing From: sender@example.com To: Schleuder Content-Type: multipart/mixed; boundary=00032557395e3572cf04760cb060 --00032557395e3572cf04760cb060 Content-Type: text/plain; charset=UTF-8 testing -- http://lindsaar.net/ Rails, RSpec and Life blog.... --00032557395e3572cf04760cb060 Content-Type: text/plain; charset=UTF-8; name="=?UTF-8?B?44Gm44GZ44GoLnR4dA==?=" Content-Disposition: attachment; filename="=?UTF-8?B?44Gm44GZ44GoLnR4dA==?=" Content-Transfer-Encoding: base64 X-Attachment-Id: f_g0uxfl510 dGhpcyBpcyBhIHRlc3QK44GT44KM44KP44Gm44GZ44Go --00032557395e3572cf04760cb060--schleuder-3.6.0/spec/fixtures/mails/charset_mails/japanese_attachment_long_name.eml000066400000000000000000000045311401002544500307360ustar00rootroot00000000000000Delivered-To: schleuder@example.org Received: by 10.231.12.67 with SMTP id w3cs164325ibw; Fri, 30 Oct 2009 01:11:12 -0700 (PDT) Received: by 10.150.44.2 with SMTP id r2mr2367210ybr.77.1256890271939; Fri, 30 Oct 2009 01:11:11 -0700 (PDT) Return-Path: Received: from mx1.test.lindsaar.net.au (mx1.test.lindsaar.net.au [210.14.110.240]) by mx.google.com with ESMTP id 25si7923673gxk.34.2009.10.30.01.11.11; Fri, 30 Oct 2009 01:11:11 -0700 (PDT) Received-SPF: neutral (google.com: 210.14.110.240 is neither permitted nor denied by domain of mikel@test.lindsaar.net) client-ip=210.14.110.240; Authentication-Results: mx.google.com; spf=neutral (google.com: 210.14.110.240 is neither permitted nor denied by domain of mikel@test.lindsaar.net) smtp.mail=mikel@test.lindsaar.net Received: from [192.168.4.253] (60-241-138-146.static.tpgi.com.au [60.241.138.146]) (using TLSv1 with cipher AES128-SHA (128/128 bits)) (No client certificate requested) (Authenticated sender: mikel) by mx1.test.lindsaar.net.au (Postfix) with ESMTPSA id 5C0186DD4CD for ; Fri, 30 Oct 2009 19:11:08 +1100 (EST) Subject: =?utf-8?B?44G+44G/44KA44KB44KC44G+44G/44KA44KB44KC44G+44G/44KA?= =?utf-8?B?44KB44KC44G+44G/44KA44KB44KC44G+44G/44KA44KB44KC44G+?= =?utf-8?B?44G/44KA44KB44KC44G+44G/44KA44KB44KC44G+44G/44KA44KB?= =?utf-8?B?44KC44G+44G/44KA44KB44KC44G+44G/44KA44KB44KC?= From: sender@example.com Content-Type: multipart/mixed; boundary=Apple-Mail-6--589811753 Message-Id: <60A112A8-F26C-4E23-95B8-4EB9F139D6A0@test.lindsaar.net> Date: Fri, 30 Oct 2009 19:11:02 +1100 To: Schleuder Mime-Version: 1.0 (Apple Message framework v1076) X-Mailer: Apple Mail (2.1076) --Apple-Mail-6--589811753 Content-Disposition: attachment; filename*0*=utf-8''%E3%81%8B%E3%81%8D%E3%81%8F%E3%81%91%E3%81%93%E3%81%8B%E3%81%8D%E3%81%8F%E3%81%91%E3%81%93%E3%81%8B%E3%81%8D%E3%81%8F%E3%81%91%E3%81%93%E3%81%8B%E3%81%8D%E3%81%8F%E3%81%91%E3%81%93%E3%81%8B; filename*1*=%E3%81%8D%E3%81%8F%E3%81%91%E3%81%93.txt Content-Type: text/plain; x-unix-mode=0644; name="=?utf-8?B?44GL44GN44GP44GR44GT44GL44GN44GP44GR44GT44GL44GN44GP?= =?utf-8?B?44GR44GT44GL44GN44GP44GR44GT44GL44GN44GP44GR44GTLnR4?= =?utf-8?B?dA==?=" Content-Transfer-Encoding: 7bit this is the data --Apple-Mail-6--589811753--schleuder-3.6.0/spec/fixtures/mails/charset_mails/japanese_iso_2022.eml000066400000000000000000000003671401002544500260310ustar00rootroot00000000000000MIME-Version: 1.0 Subject: =?UTF-8?B?44G+44G/44KA44KB44KC?= From: sender@example.com To: =?UTF-8?B?44G/44GR44KL?= Content-Type: text/plain; charset=iso-2022-jp Content-Transfer-Encoding: 7bit $B$9$_$^$;$s!#(B schleuder-3.6.0/spec/fixtures/mails/charset_mails/japanese_shift_jis.eml000066400000000000000000000005661401002544500265550ustar00rootroot00000000000000Delivered-To: schleuder@example.org Date: Wed, 28 May 2014 17:18:19 +0900 (JST) From: sender@example.com To: schleuder@example.org Subject: test Message-ID: MIME-Version: 1.0 Content-Type: text/plain; charset="Shift_JIS" Content-Transfer-Encoding: 8bit ̃[̓eXgp̃[łB Ƃ낵肢\グ܂I schleuder-3.6.0/spec/fixtures/mails/charset_mails/ks_c_5601-1987.eml000066400000000000000000000004471401002544500247230ustar00rootroot00000000000000Delivered-To: schleuder@example.org Date: Wed, 28 May 2014 17:18:19 +0900 (JST) From: sender@example.com To: schleuder@example.org Subject: test Message-ID: MIME-Version: 1.0 Content-Type: text/plain; charset="ks_c_5601-1987" Content-Transfer-Encoding: 8bit Ƽ schleuder-3.6.0/spec/fixtures/mails/charset_mails/signed_utf8.eml000066400000000000000000000107131401002544500251370ustar00rootroot00000000000000Return-Path: Delivered-To: input@example.org Received: from mx-a.example.org (mx-a.example.org [10.11.12.13]) by mx-b.example.org (Postfix) with ESMTPS id B783D9 for ; Wed, 06 Mar 2020 16:11:03 +0000 (UTC) MIME-Version: 1.0 Date: Wed, 06 Mar 2020 16:11:03 +0000 From: example@example.org To: input@example.org Subject: foobar Message-ID: Content-Type: multipart/signed; protocol="application/pgp-signature"; boundary="=_3af29082653c11eaa9c874e5f9e4031"; micalg=pgp-sha256 This is an OpenPGP/MIME signed message (RFC 4880 and 3156) --=_3af29082653c11eaa9c874e5f9e4031 Content-Type: multipart/mixed; boundary="=_7A9795606B8711EAA9CA74E5F9E4031" --=_7A9795606B8711EAA9CA74E5F9E4031 Content-Transfer-Encoding: 8bit Content-Type: text/plain; charset=UTF-8; format=flowed Hi, Wie geht es dir? Danke und liebe Grüße! Input von example.org --=_7A9795606B8711EAA9CA74E5F9E4031 Content-Transfer-Encoding: 7bit Content-Type: application/pgp-keys; name=0x4DCFFC92.asc Content-Disposition: attachment; filename=0x4DCFFC92.asc; size=3813 -----BEGIN PGP PUBLIC KEY BLOCK----- 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 LBrw =8kNQ -----END PGP PUBLIC KEY BLOCK----- --=_7A9795606B8711EAA9CA74E5F9E4031 --=_3af29082653c11eaa9c874e5f9e4031 Content-Type: application/pgp-signature; name=signature.asc Content-Disposition: attachment; filename=signature.asc; size=833 Content-Description: OpenPGP digital signature -----BEGIN PGP SIGNATURE----- iQGzBAABCgAdFiEEutGcDyP9I0JgSi5RsAgBRQs6K6QFAl5rnV0ACgkQsAgBRQs6 K6Rwawv9H1cIwmmwmJJq4xSXNHBcx1uoE38+0UNb4QrwvDZ4qTPxljrtzHecp0Jh ZGB1NrEyDA0ZX298eXQwyHbiGZ8BJAxG1akLmLKGpQ2CRsuy96G4Ot3nfdsVCwPD YHyxEH8YGk85BSpjl+RZpI7EUTLF3k9NB8szKEhqY8ZgdC4H2n4mCeXNLATO/6GP qFevJtFK8LAUy1S0lQQ/Y5zWpdT/GJs6MLURhtGGEiv4TLyzcRXpu04h2TBeDlT6 Tn5YfYn1sz55rbLtQo5jmD8PwNwcsElbNQiXPdL22JyinxRz6hBAVgPVMm/bWze6 K3RvzpQ0UoZrdhCgR3PZfe8cyJPvHMyy5g2IkvlN2BbdrqknCMkSyUlo/nmpMf3Z 78RP2TLOeG+JNaEmmF5LuhVRp86A3ItaMjUy1RRdqjRxoXdbqUjjcMiBMPg317Oj 9v/CJytsOXo0LHRQXdNkxPOzosUVDTPuafaqNwT1IwBpc5nKLTV2K3PS55tQ6566 EdSR1zEh =/aB0 -----END PGP SIGNATURE----- --=_3af29082653c11eaa9c874e5f9e4031-- schleuder-3.6.0/spec/fixtures/mails/charset_mails/simple_jis.eml000066400000000000000000000005041401002544500250530ustar00rootroot00000000000000Date: Wed, 28 May 2014 17:18:19 +0900 (JST) From: sender@example.com To: schleuder@example.org Subject: test Message-ID: MIME-Version: 1.0 Content-Type: text/plain; charset="Shift_JIS" Content-Transfer-Encoding: 8bit ̃[̓eXgp̃[łB Ƃ낵肢\グ܂I schleuder-3.6.0/spec/fixtures/mails/charset_mails/simple_jpiso2022.eml000066400000000000000000000003741401002544500257250ustar00rootroot00000000000000MIME-Version: 1.0 Subject: =?UTF-8?B?44G+44G/44KA44KB44KC?= From: Mikel Lindsaar To: =?UTF-8?B?44G/44GR44KL?= Content-Type: text/plain; charset=iso-2022-jp Content-Transfer-Encoding: 7bit $B$9$_$^$;$s!#(B schleuder-3.6.0/spec/fixtures/mails/charset_mails/simple_latin1.eml000066400000000000000000000003361401002544500254610ustar00rootroot00000000000000Subject: test To: schleuder@example.org From: sender@example.com Date: Wed, 6 Nov 2019 22:04:23 -0200 MIME-Version: 1.0 Content-Type: text/plain; charset=ISO-8859 Content-Language: en-US Content-Transfer-Encoding: 8bit schleuder-3.6.0/spec/fixtures/mails/charset_mails/simple_utf8.eml000066400000000000000000000003341401002544500251550ustar00rootroot00000000000000Subject: test To: schleuder@example.org From: sender@example.com Date: Wed, 6 Nov 2019 22:04:23 -0200 MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Language: en-US Content-Transfer-Encoding: 8bit é schleuder-3.6.0/spec/fixtures/mails/charset_mails/thunderbird-multi-alt-html.eml000066400000000000000000000067121401002544500301060ustar00rootroot00000000000000From: foo bar To: input@example.org Subject: =?UTF-8?Q?input_f=c3=bcr_Test?= Message-ID: <435093879857398573985735@example.org> Date: Fr, 12 Mar 2020 09:49:01 +0500 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:60.0) Gecko/20100101 Thunderbird/60.9.1 MIME-Version: 1.0 Content-Type: multipart/alternative; boundary="------------421BD2D66A2A11EAB33E74E5F9E4031" This is a multi-part message in MIME format. --------------421BD2D66A2A11EAB33E74E5F9E4031 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable liebes example.org team, Wie geht es euch? Wir haben uns schon Gedanken gemacht: example.org danke für euren Support! gr=C3=BC=C3=9Fe foo bar --------------421BD2D66A2A11EAB33E74E5F9E4031 Content-Type: text/html; charset=utf-8 Content-Transfer-Encoding: 8bit

liebes example.org team,

Wie geht es euch?

Wir haben uns schon Gedanken gemacht: example.org

danke für euren Support!

grüße

foo bar

--------------421BD2D66A2A11EAB33E74E5F9E4031-- schleuder-3.6.0/spec/fixtures/mails/containing-pgp-garbage.txt000066400000000000000000000012341401002544500244450ustar00rootroot00000000000000Date: Sat, 4 Jan 2020 23:42:49 +0000 From: To: schleuder@example.org Subject: Test Message-ID: <20200104234249.GB9231@example.org> MIME-Version: 1.0 Content-Type: multipart/encrypted; protocol="application/pgp-encrypted"; boundary="eAbsdosE1cNLO4uF" Content-Disposition: inline --eAbsdosE1cNLO4uF Content-Type: application/pgp-encrypted Content-Disposition: attachment Version: 1 --eAbsdosE1cNLO4uF Content-Type: application/octet-stream Content-Disposition: attachment; filename="msg.asc" -----BEGIN PGP MESSAGE----- hF4DTO8GH8gtgSMSAQdAjiYMTVwKw70Z3H8NwyZeHpPopnE1BB2L8Cs0MF95AXYw =xJbn -----END PGP MESSAGE----- --eAbsdosE1cNLO4uF-- schleuder-3.6.0/spec/fixtures/mails/encrypted+signed-inline/000077500000000000000000000000001401002544500241175ustar00rootroot00000000000000schleuder-3.6.0/spec/fixtures/mails/encrypted+signed-inline/thunderbird.eml000066400000000000000000000072571401002544500271430ustar00rootroot00000000000000Received: from [IPv6:::1] (localhost.localdomain [IPv6:::1]) by flutsch.local (Postfix) with ESMTP id 63585801DD for ; Thu, 29 Dec 2016 15:17:07 +0100 (CET) To: schleuder@example.org From: paz Subject: encrypted+signed-inline test Openpgp: id=52507B0163A8D9F0094FFE03B1A36F08069E55DE Message-ID: <216c8188-a773-fa94-d2e1-b2db4a309fed@nadir.org> Date: Thu, 29 Dec 2016 15:17:07 +0100 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Thunderbird/45.5.1 MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit -----BEGIN PGP MESSAGE----- Charset: utf-8 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 IRNo4dJ6xTzOYXQD0Wo+z5kV =gl5b -----END PGP MESSAGE----- schleuder-3.6.0/spec/fixtures/mails/encrypted+signed-mime/000077500000000000000000000000001401002544500235705ustar00rootroot00000000000000schleuder-3.6.0/spec/fixtures/mails/encrypted+signed-mime/thunderbird.eml000066400000000000000000000112001401002544500265730ustar00rootroot00000000000000Received: from [IPv6:::1] (localhost.localdomain [IPv6:::1]) by flutsch.local (Postfix) with ESMTP id 1DCDC801DD for ; Thu, 29 Dec 2016 15:09:43 +0100 (CET) To: schleuder@example.org From: paz Subject: encrypted+signed-mime test Openpgp: id=52507B0163A8D9F0094FFE03B1A36F08069E55DE Message-ID: Date: Thu, 29 Dec 2016 15:09:29 +0100 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Thunderbird/45.5.1 MIME-Version: 1.0 Content-Type: multipart/encrypted; protocol="application/pgp-encrypted"; boundary="V4nVnp5nddnPgg4bACDcs1kSu5wBuHpL9" This is an OpenPGP/MIME encrypted message (RFC 4880 and 3156) --V4nVnp5nddnPgg4bACDcs1kSu5wBuHpL9 Content-Type: application/pgp-encrypted Content-Description: PGP/MIME version identification Version: 1 --V4nVnp5nddnPgg4bACDcs1kSu5wBuHpL9 Content-Type: application/octet-stream; name="encrypted.asc" Content-Description: OpenPGP encrypted message Content-Disposition: inline; filename="encrypted.asc" -----BEGIN PGP MESSAGE----- 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 xdiqE90= =FY19 -----END PGP MESSAGE----- --V4nVnp5nddnPgg4bACDcs1kSu5wBuHpL9-- schleuder-3.6.0/spec/fixtures/mails/encrypted-inline/000077500000000000000000000000001401002544500226525ustar00rootroot00000000000000schleuder-3.6.0/spec/fixtures/mails/encrypted-inline/thunderbird.eml000066400000000000000000000056141401002544500256710ustar00rootroot00000000000000Received: from [IPv6:::1] (localhost.localdomain [IPv6:::1]) by flutsch.local (Postfix) with ESMTP id C4826801DD for ; Thu, 29 Dec 2016 15:19:35 +0100 (CET) To: schleuder@example.org From: paz Subject: encrypted-inline test Openpgp: id=52507B0163A8D9F0094FFE03B1A36F08069E55DE Message-ID: Date: Thu, 29 Dec 2016 15:19:35 +0100 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Thunderbird/45.5.1 MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit -----BEGIN PGP MESSAGE----- Charset: utf-8 hQIMA691X8Gl2MArAQ/+OQczLE7CgyUgZAg3dRWeTrNIkqlo7KMWxCyVfH310vKz rrTVFWbBeS0sOmMpN4cJSvJns2W+hJ9FnAdNtCPLC2zWhnN/4/hlWOSoE5A7cgHQ oqKcddbyCeOk0um869zL+O7GavQd3GhjwmFb9gOQVPUVGzNjkvlS/wMLGCM2287/ Fkh7TsFgmOWIY6hxZ1xI7wsk9CV33CVu4KnTUh/u+R76E1EROoPN/E5N6MYOGN0k DZ4i/qZHrnVnauFM4CfZnszY7JE6nY3QNIQohg/bMuZBeFIzacDruluIJQAhVGGf Le7W6uKPCUbvyQbJscq4wQiOA3fbdlCeScIVuR+pligZQHyCW6CVCLPlgxYnQUE+ vGOKFRsMXpjRfk/laSg+6v9r1WqaxleOW7XMUhvoQ0bya5DNnEPMhufSTCGZUv1y z11PFK+eeYWYRv+IpADRq0Bs7VxjYH4pe8iCRirboEH5F+ATW9PHSeuDQZb8e7Fw pu2oc/Zz/y9loT7UNbKyFQ1wTNNNlh/LEqXc1/KoSRAkgkLDfHD7BRG7SbXSLVIi yBD6hnQSqtgHpt0seXdUc4NRKYwJqeuTtC821YBHGFIVvqRZ6W9mHEfb+wqrHAdz OECSt0Nfn1OUQ8wcsdVv7Kv1cKVuH4VW483vj8dlipLRY+T6SqqQcM5V3buEGXaF AgwDAAAAAAAAAAABD/9AH8fdSTd1GiSOlArB9a3d+/MQ80uZQSQZZk1mqYWPS2+W FQH/8GuNDgXBtoUoVu4tR9FZsYhzSWvSXYF6wNP+OyatlZjVYxYbRfv0pgtlrmiD vtmFIJYAQpxwvta+CfKzQjM2UZeYbcPOVrA/t0AfscWdwX8E9FrhvoHzT1wfU7BR dGqj+IV2EJ3+8K6mpjLIvcGkhai8rbCF1vvWgMBMffUaNmCVuXaWPvoZ4kjZOjio TkN6cCmDul9z77XMUCMROTExTIkZseoSbzH6SD2bQcWRMvVHoWxJ0CdLh0nb0nsD jYFR9NT1mVLYedqNAfrR1xdos+Hcs8YbVikFH4ZJziHfbbFN4HkMNEABI6X38rsE NaDE8ea85IVJIhQKqrf3wOUB0VlqfZasfzXPKrYsynk+qil6py3NqebpBy0vuJs+ Esr5tiBoQGZp0U4Z3XKuR2yspNwVZE4ysWfVXfF2KI5/iTrowsqug5YK5iJw+fM3 OPX0o+bQoi0nWt9okCRRCISez/FNEDytebYdGX98trmJA+UDboTKj+yf12vpZd47 JYma/F8Bb/kXhKFAetIRv7q69I8P6wrCbBEEeMBR/aXVBLaYYgkDP74xPrggONCO 0BD7CBHH85y/BYLBMTeH1aOCjv7gXM+gOwFHnNtxJgPhfhwma2Sx6Ttfm6k9roUC DAOnLuUXmtC57QEQAKBKg7cKZKaFgBOys/2DAsqUJiHqnvAyDW7LerncA7yx3WWV cFeZCa+ecRcO1iLnJa6GO/SVex9UNJrLXiYKEYKD9hIIBFRuMIWuTmp9eU4QW0E9 /kjXCJxfN8gpDlnKzV6uK77JHuI4qr/ZpMLIYdJBJcRKLB3ufP5ryKTbZ50MjnZn YYvjIM/28hB0MIhw8y0WC4LFt2B8uCCdw6YmC0rchVyn4ByX9UJa+lOtxecHYps+ wH0FgncjRJF5KhmDYEIJhZ96R1fWfm6SC2jjWBxJzu0SYd9AX/6nnYV2mbH7WxB5 F0uDlm8MTx9I2dIypfhdkcPMXnuS8t4UY/RSA2JiGMIfTcZ31POIIXl2dmH+/74z jjq0qYyHrzF+U7uX1LN2EJBtDQVI19wcgGRUUB2ouJjIKv/iZYOIvg2YC46hBV9G 7W8k7yAUdW1sPDAQMSjLmaQIqK0Ou/UQJyxhuiy21BJAQWTFk+ikweoIWclYziKa Zlnkl4IywPmUB2TywUnNh9H9yWW+OQDWFaWEPRVpSY2SiBZpfzq5AQKy3rOVUS91 JwiQAW6WGobtHG+84IxblfGxFSGuDOzCcN5FTkMRK/H/6evYTioKTh9XrvnaKwkf HHuk6WF8sNP0GjxdYgi6C9iTK4ZzLfrVb9XQ/cuBxhmtR3ahGxgX7BG7AfNk0mcB hUiZoD55KEYRkCLEa3OTcg8HCDiqGn9TeLqL0Q5ZqSYydxlLxhFAOc57SmznzWRD wuW2uo0nN6EgrKrWe8MvKXyE2/0tbKqersCXEV0SnozBlom/zCs0zZ4AKChN1fYc gIXCntFc =7wno -----END PGP MESSAGE----- schleuder-3.6.0/spec/fixtures/mails/encrypted-mime/000077500000000000000000000000001401002544500223235ustar00rootroot00000000000000schleuder-3.6.0/spec/fixtures/mails/encrypted-mime/thunderbird.eml000066400000000000000000000074271401002544500253460ustar00rootroot00000000000000Received: from [IPv6:::1] (localhost.localdomain [IPv6:::1]) by flutsch.local (Postfix) with ESMTP id DAFE5801DD for ; Thu, 29 Dec 2016 15:13:34 +0100 (CET) To: schleuder@example.org From: paz Subject: encrypted-mime test Openpgp: id=52507B0163A8D9F0094FFE03B1A36F08069E55DE Message-ID: <51db1a44-b9b7-1390-b8ce-a0980101842d@nadir.org> Date: Thu, 29 Dec 2016 15:13:34 +0100 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Thunderbird/45.5.1 MIME-Version: 1.0 Content-Type: multipart/encrypted; protocol="application/pgp-encrypted"; boundary="9JN8w93dvNGWNV5ifxvV0OtHWs5PxOc8A" This is an OpenPGP/MIME encrypted message (RFC 4880 and 3156) --9JN8w93dvNGWNV5ifxvV0OtHWs5PxOc8A Content-Type: application/pgp-encrypted Content-Description: PGP/MIME version identification Version: 1 --9JN8w93dvNGWNV5ifxvV0OtHWs5PxOc8A Content-Type: application/octet-stream; name="encrypted.asc" Content-Description: OpenPGP encrypted message Content-Disposition: inline; filename="encrypted.asc" -----BEGIN PGP MESSAGE----- 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 =jj1e -----END PGP MESSAGE----- --9JN8w93dvNGWNV5ifxvV0OtHWs5PxOc8A-- schleuder-3.6.0/spec/fixtures/mails/encrypted-to-absent-key.txt000066400000000000000000000023661401002544500246260ustar00rootroot00000000000000Date: Sat, 4 Jan 2020 23:42:49 +0000 From: To: schleuder@example.org Subject: Test Message-ID: <20200104234249.GB9231@example.org> MIME-Version: 1.0 Content-Type: multipart/encrypted; protocol="application/pgp-encrypted"; boundary="eAbsdosE1cNLO4uF" Content-Disposition: inline --eAbsdosE1cNLO4uF Content-Type: application/pgp-encrypted Content-Disposition: attachment Version: 1 --eAbsdosE1cNLO4uF Content-Type: application/octet-stream Content-Disposition: attachment; filename="msg.asc" -----BEGIN PGP MESSAGE----- hQGMA+8L5wLeonReAQv/ch+gZBhnP0ikFnkmEXB50e3oWlP7/Gc0hRetb6s5I8u4 dJOt9FUpaWiKg/OryBafJ889VtE7ujO2d8T+D0xwqiE9JRNzP3DiWiXgNpKw5pmN L6R4+skZ9UK009AzxWSivgg6fJIpk8i022n9c5DPK4sMOE2jUYV7C2BMzXcSq8jf vr5Wet3lf2yzfU+Pb62s8N1y/qg0PZrJb/0ddnaY4DDMPb4db3H2fuOEzuHnyxOK WiphCGWSKqKUUWt/x/01GABWBDCy/5HB5ow1o43u8KDriTVB765dd0aS2QGqhLD8 yvhEnzjb1DRz5Bml7NOXKeueFL80S0vge1AKT1YOf1bW1YfTEpn0jiLr8zasd41c c7cM6SGX6PFV6xGTqMgHLBZaN7Xj4ijgqZfPslYJp4iqjyQ18y1S3zMBDLc3s+9T iihTi2Ve2D2nI7Xb1Cl/UAgRDin7pQT39UBsHtrKHbpf0NTKYQKzHk+0K+VZn1Bq a89bFZrfiT+iMXovAzx20loBzk6GUrmSRSgngW7ai0se4nEQ7Vj8xJV/awmBq8Oz O8UtXiQlIoqOXH07aLxZm819BRNy66XiRUsW0bxN/pzSbOlhivIXYm5ypy5UWEsl hGHDxswJibLDdpc= =pSCD -----END PGP MESSAGE----- --eAbsdosE1cNLO4uF-- schleuder-3.6.0/spec/fixtures/mails/encrypted-to-passphrase.txt000066400000000000000000000013461401002544500247320ustar00rootroot00000000000000Date: Sat, 4 Jan 2020 23:42:49 +0000 From: To: schleuder@example.org Subject: Test Message-ID: <20200104234249.GB9231@example.org> MIME-Version: 1.0 Content-Type: multipart/encrypted; protocol="application/pgp-encrypted"; boundary="eAbsdosE1cNLO4uF" Content-Disposition: inline --eAbsdosE1cNLO4uF Content-Type: application/pgp-encrypted Content-Disposition: attachment Version: 1 --eAbsdosE1cNLO4uF Content-Type: application/octet-stream Content-Disposition: attachment; filename="msg.asc" -----BEGIN PGP MESSAGE----- jA0ECQMCk858png0tIj/0lQBvHbaDcW9nElJfL0tgFhEnZv3847kDXaRpYAaQhAY TmHzD51Z7uUbalJSxgmLnBVFRFop2sKSmba1sqtlhszYFjTRerlWAJsb5vNZ1KIB 1kyOuBU= =42m3 -----END PGP MESSAGE----- --eAbsdosE1cNLO4uF-- schleuder-3.6.0/spec/fixtures/mails/exchange.eml000066400000000000000000000051521401002544500216650ustar00rootroot00000000000000From: someone@example.org To: schleuder@example.org Message-ID: <098234lkj098324lkajsdfklj09er09a842d@localhost> Date: Thu, 01 01 2017 12:13:14 +0100 Subject: hotmail mangled message Content-Type: multipart/mixed; boundary="_003_MIME_" MIME-Version: 1.0 X-OriginatorOrg: hotmail.com X-MS-Exchange-CrossTenant-originalarrivaltime: 29 May 2017 00:00:00.0000 (UTC) X-MS-Exchange-CrossTenant-fromentityheader: Internet X-MS-Exchange-CrossTenant-id: dajfkajfkljaklfj X-MS-Exchange-Transport-CrossTenantHeadersStamped: HEADERSTAMP --_003_MIME_ Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable --_003_MIME_ Content-Type: application/pgp-encrypted; name="PGPMIME version identification" Content-Description: PGP/MIME version identification Content-Disposition: attachment; filename="PGPMIME version identification"; size=12; creation-date="Mon, 29 May 2017 00:00:00 GMT"; modification-date="Mon, 29 May 2017 00:00:00 GMT" Content-ID: Content-Transfer-Encoding: base64 VmVyc2lvbjogMQoK --_003_MIME_ Content-Type: application/octet-stream; name="encrypted.asc" Content-Description: OpenPGP encrypted message.asc Content-Disposition: attachment; filename="encrypted.asc"; creation-date="Mon, 29 May 2017 00:00:00 GMT"; modification-date="Mon, 29 May 2017 00:00:00 GMT" Content-ID: Content-Transfer-Encoding: base64 LS0tLS1CRUdJTiBQR1AgTUVTU0FHRS0tLS0tCgpoUUlNQTY5MVg4R2wyTUFyQVEvL1d3SEx1Nlp2 WE15M0VkemlaYUZnaytqQ2NxOHZXS3dTc1FQS25zWTdSRWxKCkpsdENta1JSZ2d0ajVDbDNaWWIv eVhLVEhNUElUd0hnQ3F3MVFhVFpIT2ZCT3FET3lyWVJndExEWHpabXd3RnQKQVdSWmVDWndQenJp OElKbmJaMHdlaUhMRzFiMzR2c1pqc2pIN1E3dHd4clRVbEFmbTJuUXY3TU9naFpibFRKQwpOUlY5 ekdSM0lNa0JEbURhMy9kUkRkam5kaG02dFJxMVFNS1FjdUNYekpScHUwQlNuMFFacnFHcitKdmQz TnN1CjVqTlR4dHQyV3Z6d296eHdHbVltckZ4U3E3L2VXdjdTWnFEMWFicEFQY0RrQmxIdkdobi9a Z29sZUovVGJKb2oKaWpRb1RzUDQ5YnFWUm5HRUtFK3RWVmt5dmpmeFgrTDNIUGpVdjVheFpoRFRp ejNsQnZBWWRTZlZ4cHFDWTVHMApDVWFJNFlxb3lEUlY3a2UyY0FxOFV5ODA2akFmYkUzMi9qUGlQ VkxjUDROem9WRGVyRkZ5NDBVMFp6cGtLL2pCCnpNdUVxZE9nd09xZUtHdkZCMEd5OWFXcVZYUWJZ Y1FoZ0dRV3Jxck9Jb1pTbmt3SnlhSjdqNXIvV0tFMDZuRVUKdEVXcEFEWDlHVlRFL1EyL0ZJMzB6 UCtzMnU2S2FLclB5dXZORTZXMk1abFNZMFUzaVFtY1dwQlFQZUZGOEhhYQpMM1hvMy9SdVFCRlBX S2hWTzh4ZlAxRllVc2lnallYcjJIcGpXaVdBejkxVG00MC95RjRObWN0STZEejFzaExTCkI2aGds Z2hneFZEdkZIcUprREVlRGk2R1lsTTVaaGg0WklpeDBlVWFjcGRybVM3TUZaenhzMjA0T3prQ21n UFMKV1FHbWV6NWlvNmxtbUZLZlhWYXJOajBwVHZHOVUzekJGUUozWldEUUZDZCtidGtrUm5ndWhH K3NiN2taZmkrTAo1U1ZqZDNWRGRReTU5TlNIbzk4Ukl2dEtIZlhnU0l1WU5Lc2pDTHpOcFhMNGM0 WGYzY0U0ZndNWQo9VXU1SAotLS0tLUVORCBQR1AgTUVTU0FHRS0tLS0tCg== --_003_MIME_ schleuder-3.6.0/spec/fixtures/mails/exchange_no_parts.eml000066400000000000000000000030071401002544500235670ustar00rootroot00000000000000From foobar@outlook.com Wed Jul 12 10:40:53 2017 Received: from bla.eurprd02.prod.outlook.com ([fe80::dead:beef]) by bar.eurprd02.prod.outlook.com ([fe80::dead:beef%42]) with mapi id 00.00.0000.00; Wed, 12 Jul 2017 00:00:00 +0000 From: Foo Bla Bar To: "schleuder@example.org" Subject: aSubject Thread-Topic: aSubject Thread-Index: jafkjakfjaklfjkljklj Date: Wed, 12 Jul 2017 00:00:00 +0000 Message-ID: Accept-Language: de-DE, en-US Content-Language: de-DE X-MS-Has-Attach: X-MS-TNEF-Correlator: authentication-results: example.org; dkim=none (message not signed) header.d=none;example.org; dmarc=none action=none header.from=outlook.com; x-incomingtopheadermarker: OriginalChecksum:somechecksum;UpperCasedChecksum:anotherchecksum;SizeAsReceived:6666;Count:23 x-ms-exchange-messagesentrepresentingtype: 1 x-tmn: [akfjkafjkajf+ajkfhajkfhjhkjfahfjk] x-ms-publictraffictype: Email x-incomingheadercount: 23 x-eopattributedmessage: 0 x-exchange-antispam-report-test: UriScan:; spamdiagnosticoutput: 1:99 spamdiagnosticmetadata: NSPM Content-Type: text/plain; charset="us-ascii" Content-ID: Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 X-OriginatorOrg: outlook.com X-MS-Exchange-CrossTenant-originalarrivaltime: 12 Jul 2017 00:00:00.0000 (UTC) X-MS-Exchange-CrossTenant-fromentityheader: Internet X-MS-Exchange-CrossTenant-id: aaaa-bbbb-cccc-dddd-aaaaaaaaaaaa X-MS-Exchange-Transport-CrossTenantHeadersStamped: DEADBEEF bla-vla lu du schleuder-3.6.0/spec/fixtures/mails/mail_with_pgp_boundaries_in_body.txt000066400000000000000000000005151401002544500267040ustar00rootroot00000000000000To: list@example.org From: test@example.org Subject: Test Message-ID: <8db04406-e2ab-fd06-d4c5-c19b5765c52b@example.com> Date: Tue, 27 Dec 2016 17:18:57 +0100 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 7bit Test -----BEGIN PGP MESSAGE----- Only to show what is between here... -----END PGP MESSAGE----- schleuder-3.6.0/spec/fixtures/mails/multipart-alternative/000077500000000000000000000000001401002544500237365ustar00rootroot00000000000000schleuder-3.6.0/spec/fixtures/mails/multipart-alternative/thunderbird-multi-alt-signed.eml000066400000000000000000000052101401002544500321220ustar00rootroot00000000000000To: paz@nadir.org From: paz Subject: multi/alt test signed Openpgp: id=52507B0163A8D9F0094FFE03B1A36F08069E55DE Message-ID: <8aff12ad-3045-a69c-bdcc-f1638c699623@nadir.org> Date: Sun, 12 Feb 2017 22:26:47 +0100 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Thunderbird/45.7.0 MIME-Version: 1.0 Content-Type: multipart/signed; micalg=pgp-sha512; protocol="application/pgp-signature"; boundary="b3ViXpO41teSXWPCLNnj2VCalcqUBwURw" This is an OpenPGP/MIME signed message (RFC 4880 and 3156) --b3ViXpO41teSXWPCLNnj2VCalcqUBwURw Content-Type: multipart/mixed; boundary="wq1LskS7mbBfokmGQFKSgUaVwAn5TCnAA"; protected-headers="v1" From: paz To: paz@nadir.org Message-ID: <8aff12ad-3045-a69c-bdcc-f1638c699623@nadir.org> Subject: multi/alt test signed --wq1LskS7mbBfokmGQFKSgUaVwAn5TCnAA Content-Type: multipart/alternative; boundary="------------9168A8DB20220BC208511980" This is a multi-part message in MIME format. --------------9168A8DB20220BC208511980 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable _*This is a test.*_ --------------9168A8DB20220BC208511980 Content-Type: text/html; charset=utf-8 Content-Transfer-Encoding: quoted-printable

This is a test.

--------------9168A8DB20220BC208511980-- --wq1LskS7mbBfokmGQFKSgUaVwAn5TCnAA-- --b3ViXpO41teSXWPCLNnj2VCalcqUBwURw Content-Type: application/pgp-signature; name="signature.asc" Content-Description: OpenPGP digital signature Content-Disposition: attachment; filename="signature.asc" -----BEGIN PGP SIGNATURE----- iQIzBAEBCgAdFiEEUlB7AWOo2fAJT/4DsaNvCAaeVd4FAlig0xoACgkQsaNvCAae Vd7QzQ//a3DZKrIJeABLD/RfB4rZVmxat+kJAjsNKSnJk7sfxrtcCsDTlNY2QGGt SEe8f3HtpcOjFMVqH7FVXSaXM+E/emmPP19js2c2uLVTZi9SLkvF+NX/4dOXq0nR 6sVwEokN0/dTu4aV8cdTenKFUdIJzAjpfWgAPFOmyCe2KDSzyLrkmYbtBgSqO6l3 3S5rk4AqVVYrklWp50C+oKxVyE57Rs9848YOn3awRvFT+aocdH+UI74h9PD9Hx8z OhaT9qNEJ/KJGYjjCRv4Ls5zbKHok4RCuFozRU9UEvBDzT/NzWnMLWL90eSh4akV U/MMLGRSaB27+KBLRuxsre/eSQt6cCQWDGZbkf4VLKTEHtIKWnNPRXzSUb9SQ4xa zjHqKDVBZmHW8ftqwWK2fU1EGa9cAOpBqFyIdA/XPRX6w4n0r/Wo+ZVRtVPBiZEv K0SMNpXidfo07MgC9urEvPZi8Bo5EqwZYSpVUZsLQSWKvkw+n/+APzIaXyjP1DNs 4yFc4pqAErtokiftjT2r4P3gCXDTAOJBzHP9e1FzMS4rW9dLw+aa7FyWUvXqiRzd F0X/Ah8f8asr9Tpt6uoDYpRZ3Ny3R4/Gr0U9CzqBFbg0PfN1PJmOl2wGc6giIiAx Qf3wFp+7EmQJzlfLdEKyb4Nl5n2ColDVcD6r1pA4QNuh0vdgwYs= =7nKg -----END PGP SIGNATURE----- --b3ViXpO41teSXWPCLNnj2VCalcqUBwURw-- schleuder-3.6.0/spec/fixtures/mails/multipart-alternative/thunderbird-multi-alt-unsigned.eml000066400000000000000000000024141401002544500324700ustar00rootroot00000000000000Return-Path: X-Original-To: paz@duckdalbe.org Delivered-To: paz@duckdalbe.org Received: from flutsch.local (x4dbbbe7a.dyn.telefonica.de [77.187.190.122]) by duckdalbe.org (Postfix) with ESMTPSA id DC98332097 for ; Sun, 12 Feb 2017 22:27:50 +0100 (CET) From: paz Subject: multi/alt test unsigned To: paz@nadir.org Openpgp: id=52507B0163A8D9F0094FFE03B1A36F08069E55DE Message-ID: Date: Sun, 12 Feb 2017 22:27:48 +0100 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Thunderbird/45.7.0 MIME-Version: 1.0 Content-Type: multipart/alternative; boundary="------------995F058E0A221863BAC4E3E7" This is a multi-part message in MIME format. --------------995F058E0A221863BAC4E3E7 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 7bit _*This is a test.*_ --------------995F058E0A221863BAC4E3E7 Content-Type: text/html; charset=utf-8 Content-Transfer-Encoding: 7bit

This is a test.

--------------995F058E0A221863BAC4E3E7-- schleuder-3.6.0/spec/fixtures/mails/not_bounces/000077500000000000000000000000001401002544500217175ustar00rootroot00000000000000schleuder-3.6.0/spec/fixtures/mails/not_bounces/Bug_948980-_marked_as_pending_in_schleuder.eml000066400000000000000000000156501401002544500323220ustar00rootroot00000000000000Received: from immer7-21.glei.ch ([192.168.1.91]) by immer12-24.glei.ch with esmtps (TLSv1.2:ECDHE-RSA-AES256-GCM-SHA384:256) (Exim 4.92) id 1irm4e-0006qg-IY for team@schleuder.org; Wed, 15 Jan 2020 18:03:20 +0100 Received: from localhost ([127.0.0.1]) by immer7-21.glei.ch with esmtp (Exim 4.92.3) id 1irm4e-0008VW-1F for team@schleuder.org; Wed, 15 Jan 2020 18:03:20 +0100 Received: from immer7-21.glei.ch ([127.0.0.1]) by localhost (immer7-21.glei.ch [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id BsQ6Lnw6HFJD for ; Wed, 15 Jan 2020 18:03:14 +0100 Received: from mailly.debian.org ([82.195.75.114]) by immer7-21.glei.ch with esmtps (TLSv1.2:ECDHE-RSA-AES256-GCM-SHA384:256) (Exim 4.92.3) id 1irm4Y-0008UB-8q for team@schleuder.org; Wed, 15 Jan 2020 18:03:14 +0100 Received: from ticharich.debian.org ([2607:f8f0:614:1::1274:64]:40110)=0D=0A from C=NA,ST=NA,L=Ankh Morpork,O=Debian SMTP,OU=Debian SMTP CA,CN=ticharich.debian.org,EMAIL=hostmaster@ticharich.debian.org (verified)=0D=0A by mailly.debian.org with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256)=0D=0A (Exim 4.92)=0D=0A (envelope-from )=0D=0A id 1irm4S-0000Ua-Eq=0D=0A for team@schleuder.org; Wed, 15 Jan 2020 17:03:08 +0000 Received: from localhost ([::1]:49224 helo=ticharich.debian.org) by ticharich.debian.org with esmtp (Exim 4.92) (envelope-from ) id 1irm4R-00088i-2J for team@schleuder.org; Wed, 15 Jan 2020 17:03:07 +0000 Received: from mailly.debian.org ([2001:41b8:202:deb:6564:a62:52c3:4b72]:51344)=0D=0A from C=NA,ST=NA,L=Ankh Morpork,O=Debian SMTP,OU=Debian SMTP CA,CN=mailly.debian.org,EMAIL=hostmaster@mailly.debian.org (verified)=0D=0A by ticharich.debian.org with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256)=0D=0A (Exim 4.92)=0D=0A (envelope-from )=0D=0A id 1irm4Q-000886-SQ=0D=0A for dispatch+schleuder@tracker.debian.org; Wed, 15 Jan 2020 17:03:06 +0000 Received: from quantz.debian.org ([2607:f8f0:614:1::1274:73]:52730)=0D=0A from C=NA,ST=NA,L=Ankh Morpork,O=Debian SMTP,OU=Debian SMTP CA,CN=quantz.debian.org,EMAIL=hostmaster@quantz.debian.org (verified)=0D=0A by mailly.debian.org with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256)=0D=0A (Exim 4.92)=0D=0A (envelope-from )=0D=0A id 1irm4P-0000U6-Dj=0D=0A for dispatch+schleuder@tracker.debian.org; Wed, 15 Jan 2020 17:03:05 +0000 Received: from qa by quantz.debian.org with local (Exim 4.92) (envelope-from ) id 1irm4O-00028a-4N for dispatch+schleuder@tracker.debian.org; Wed, 15 Jan 2020 17:03:04 +0000 Received: from buxtehude.debian.org ([2607:f8f0:614:1::1274:39]:51042)=0D=0A from C=NA,ST=NA,L=Ankh Morpork,O=Debian SMTP,OU=Debian SMTP CA,CN=buxtehude.debian.org,EMAIL=hostmaster@buxtehude.debian.org (verified)=0D=0A by quantz.debian.org with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256)=0D=0A (Exim 4.92)=0D=0A (envelope-from )=0D=0A id 1irm4O-00027y-2S=0D=0A for schleuder@packages.qa.debian.org; Wed, 15 Jan 2020 17:03:04 +0000 Received: from debbugs by buxtehude.debian.org with local (Exim 4.92) (envelope-from ) id 1irm4N-0007aH-MJ; Wed, 15 Jan 2020 17:03:03 +0000 Received: via spool by 948980-submitter@bugs.debian.org id=U948980.157910757827991 (code U ref 948980); Wed, 15 Jan 2020 17:03:02 +0000 Received: (at 948980-submitter) by bugs.debian.org; Wed, 15 Jan 2020 16:59:38 +0000 Received: from mailly.debian.org ([2001:41b8:202:deb:6564:a62:52c3:4b72]:55084)=0D=0A from C=NA,ST=NA,L=Ankh Morpork,O=Debian SMTP,OU=Debian SMTP CA,CN=mailly.debian.org,EMAIL=hostmaster@mailly.debian.org (verified)=0D=0A by buxtehude.debian.org with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256)=0D=0A (Exim 4.92)=0D=0A (envelope-from )=0D=0A id 1irm14-0007HD-1p=0D=0A for 948980-submitter@bugs.debian.org; Wed, 15 Jan 2020 16:59:38 +0000 Received: from godard.debian.org ([209.87.16.44]:52232)=0D=0A from C=NA,ST=NA,L=Ankh Morpork,O=Debian SMTP,OU=Debian SMTP CA,CN=clientcerts/godard.debian.org,EMAIL=hostmaster@clientcerts/godard.debian.org (verified)=0D=0A by mailly.debian.org with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256)=0D=0A (Exim 4.92)=0D=0A (envelope-from )=0D=0A id 1irm12-0000MR-EO=0D=0A for 948980-submitter@bugs.debian.org; Wed, 15 Jan 2020 16:59:36 +0000 Received: by godard.debian.org (Postfix, from userid 3510) id D6CD1A0EC0; Wed, 15 Jan 2020 16:59:34 +0000 Resent-Date: Wed, 15 Jan 2020 17:03:02 +0000 Resent-From: Debian BTS Resent-To: Georg Faerber Resent-Message-ID: Date: Wed, 15 Jan 2020 16:59:34 +0000 From: Georg Faerber Sender: noreply@salsa.debian.org Reply-To: Georg Faerber , 948980-quiet@bugs.debian.org To: 948980-submitter@bugs.debian.org Message-ID: <5e1f44f6c9fc2_37682ab64d19cbc48283@godard.mail> References: <20200115150418.GH26536@debian> Subject: Bug#948980: marked as pending in schleuder Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 7bit X-Virus-Scanned: amavisd-new at glei.ch X-Loop: owner@bugs.debian.org Original-Sender: noreply@salsa.debian.org X-Loop: owner@bugs.debian.org X-Debian-PR-Message: report 948980 X-Debian-PR-Package: schleuder X-Debian-PR-Keywords: X-Debian-PR-Source: schleuder X-Spam-Bayes: score:0.0000 Tokens: new, 16; hammy, 107; neutral, 24; spammy, 6. spammytokens:0.999-1--H*RT:sk:noreply, 0.993-1--HAuto-Submitted:auto-generated, 0.958-+--H*r:sk:noreply, 0.950-+--H*F:U*noreply, 0.919-+--H*rp:U*noreply hammytokens:0.000-+--sk:salsa.d, 0.000-+--sk:salsad, 0.000-+--UD:salsa.debian.org, 0.000-+--salsadebianorg, 0.000-+--salsa.debian.org Auto-Submitted: auto-generated Delivered-To: schleuder@packages.qa.debian.org Delivered-To: dispatch+schleuder@tracker.debian.org X-Loop: dispatch@tracker.debian.org X-Distro-Tracker-Keyword: bts X-Distro-Tracker-Package: schleuder List-Id: X-Debian: tracker.debian.org X-Debian-Package: schleuder X-PTS-Package: schleuder X-PTS-Keyword: bts Precedence: list List-Unsubscribe: Control: tag -1 pending Hello, Bug #948980 in schleuder reported by you has been fixed in the Git repository and is awaiting an upload. You can see the commit message below and you can check the diff of the fix at: https://salsa.debian.org/ruby-team/schleuder/commit/d88717ad33d773736929d9d3ecb0eaace0779c1f ------------------------------------------------------------------------ debian/patches: Add patch to add List-Id header to admin notifications Closes: #948980 ------------------------------------------------------------------------ (this message was generated automatically) -- Greetings https://bugs.debian.org/948980 schleuder-3.6.0/spec/fixtures/mails/not_bounces/Bug_948981-_marked_as_pending_in_schleuder.eml000066400000000000000000000162371401002544500323250ustar00rootroot00000000000000Received: from immer7-21.glei.ch ([192.168.1.91]) by immer12-24.glei.ch with esmtps (TLSv1.2:ECDHE-RSA-AES256-GCM-SHA384:256) (Exim 4.92) id 1irm4d-0006qL-Oz for team@schleuder.org; Wed, 15 Jan 2020 18:03:19 +0100 Received: from localhost ([127.0.0.1]) by immer7-21.glei.ch with esmtp (Exim 4.92.3) id 1irm4d-0008VP-4b for team@schleuder.org; Wed, 15 Jan 2020 18:03:19 +0100 Received: from immer7-21.glei.ch ([127.0.0.1]) by localhost (immer7-21.glei.ch [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 7tWjDBBn5KEd for ; Wed, 15 Jan 2020 18:03:14 +0100 Received: from muffat.debian.org ([209.87.16.33]) by immer7-21.glei.ch with esmtps (TLSv1.2:ECDHE-RSA-AES256-GCM-SHA384:256) (Exim 4.92.3) id 1irm4Y-0008U4-Dr for team@schleuder.org; Wed, 15 Jan 2020 18:03:14 +0100 Received: from ticharich.debian.org ([2607:f8f0:614:1::1274:64]:48876)=0D=0A from C=NA,ST=NA,L=Ankh Morpork,O=Debian SMTP,OU=Debian SMTP CA,CN=ticharich.debian.org,EMAIL=hostmaster@ticharich.debian.org (verified)=0D=0A by muffat.debian.org with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256)=0D=0A (Exim 4.92)=0D=0A (envelope-from )=0D=0A id 1irm4Q-0007Jl-Vt=0D=0A for team@schleuder.org; Wed, 15 Jan 2020 17:03:06 +0000 Received: from localhost ([::1]:49210 helo=ticharich.debian.org) by ticharich.debian.org with esmtp (Exim 4.92) (envelope-from ) id 1irm4Q-00088E-LN for team@schleuder.org; Wed, 15 Jan 2020 17:03:06 +0000 Received: from muffat.debian.org ([2607:f8f0:614:1::1274:33]:58328)=0D=0A from C=NA,ST=NA,L=Ankh Morpork,O=Debian SMTP,OU=Debian SMTP CA,CN=muffat.debian.org,EMAIL=hostmaster@muffat.debian.org (verified)=0D=0A by ticharich.debian.org with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256)=0D=0A (Exim 4.92)=0D=0A (envelope-from )=0D=0A id 1irm4Q-000887-H3=0D=0A for dispatch+schleuder@tracker.debian.org; Wed, 15 Jan 2020 17:03:06 +0000 Received: from quantz.debian.org ([2607:f8f0:614:1::1274:73]:57878)=0D=0A from C=NA,ST=NA,L=Ankh Morpork,O=Debian SMTP,OU=Debian SMTP CA,CN=quantz.debian.org,EMAIL=hostmaster@quantz.debian.org (verified)=0D=0A by muffat.debian.org with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256)=0D=0A (Exim 4.92)=0D=0A (envelope-from )=0D=0A id 1irm4Q-0007JW-8K=0D=0A for dispatch+schleuder@tracker.debian.org; Wed, 15 Jan 2020 17:03:06 +0000 Received: from qa by quantz.debian.org with local (Exim 4.92) (envelope-from ) id 1irm4P-0002Bn-Oq for dispatch+schleuder@tracker.debian.org; Wed, 15 Jan 2020 17:03:05 +0000 Received: from buxtehude.debian.org ([2607:f8f0:614:1::1274:39]:51054)=0D=0A from C=NA,ST=NA,L=Ankh Morpork,O=Debian SMTP,OU=Debian SMTP CA,CN=buxtehude.debian.org,EMAIL=hostmaster@buxtehude.debian.org (verified)=0D=0A by quantz.debian.org with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256)=0D=0A (Exim 4.92)=0D=0A (envelope-from )=0D=0A id 1irm4P-0002BJ-Mx=0D=0A for schleuder@packages.qa.debian.org; Wed, 15 Jan 2020 17:03:05 +0000 Received: from debbugs by buxtehude.debian.org with local (Exim 4.92) (envelope-from ) id 1irm4P-0007ab-Fn; Wed, 15 Jan 2020 17:03:05 +0000 Received: via spool by 948981-submitter@bugs.debian.org id=U948981.157910757828002 (code U ref 948981); Wed, 15 Jan 2020 17:03:04 +0000 Received: (at 948981-submitter) by bugs.debian.org; Wed, 15 Jan 2020 16:59:38 +0000 Received: from mailly.debian.org ([2001:41b8:202:deb:6564:a62:52c3:4b72]:55082)=0D=0A from C=NA,ST=NA,L=Ankh Morpork,O=Debian SMTP,OU=Debian SMTP CA,CN=mailly.debian.org,EMAIL=hostmaster@mailly.debian.org (verified)=0D=0A by buxtehude.debian.org with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256)=0D=0A (Exim 4.92)=0D=0A (envelope-from )=0D=0A id 1irm14-0007HC-1q=0D=0A for 948981-submitter@bugs.debian.org; Wed, 15 Jan 2020 16:59:38 +0000 Received: from godard.debian.org ([209.87.16.44]:52230)=0D=0A from C=NA,ST=NA,L=Ankh Morpork,O=Debian SMTP,OU=Debian SMTP CA,CN=clientcerts/godard.debian.org,EMAIL=hostmaster@clientcerts/godard.debian.org (verified)=0D=0A by mailly.debian.org with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256)=0D=0A (Exim 4.92)=0D=0A (envelope-from )=0D=0A id 1irm12-0000MQ-BS=0D=0A for 948981-submitter@bugs.debian.org; Wed, 15 Jan 2020 16:59:36 +0000 Received: by godard.debian.org (Postfix, from userid 3510) id DA71BA0D9A; Wed, 15 Jan 2020 16:59:34 +0000 Resent-Date: Wed, 15 Jan 2020 17:03:04 +0000 Resent-From: Debian BTS Resent-To: Georg Faerber Resent-Message-ID: Date: Wed, 15 Jan 2020 16:59:34 +0000 From: Georg Faerber Sender: noreply@salsa.debian.org Reply-To: Georg Faerber , 948981-quiet@bugs.debian.org To: 948981-submitter@bugs.debian.org Message-ID: <5e1f44f6ccc01_37683fd3c001e4f0829f3@godard.mail> References: <20200115150937.GI26536@debian> Subject: Bug#948981: marked as pending in schleuder Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 7bit X-Virus-Scanned: amavisd-new at glei.ch X-Loop: owner@bugs.debian.org Original-Sender: noreply@salsa.debian.org X-Loop: owner@bugs.debian.org X-Debian-PR-Message: report 948981 X-Debian-PR-Package: schleuder X-Debian-PR-Keywords: fixed-upstream X-Debian-PR-Source: schleuder X-Spam-Bayes: score:0.0000 Tokens: new, 16; hammy, 122; neutral, 34; spammy, 6. spammytokens:0.999-1--H*RT:sk:noreply, 0.993-1--HAuto-Submitted:auto-generated, 0.958-+--H*r:sk:noreply, 0.950-+--H*F:U*noreply, 0.919-+--H*rp:U*noreply hammytokens:0.000-+--sk:salsa.d, 0.000-+--sk:salsad, 0.000-+--UD:salsa.debian.org, 0.000-+--salsadebianorg, 0.000-+--salsa.debian.org Auto-Submitted: auto-generated Delivered-To: schleuder@packages.qa.debian.org Delivered-To: dispatch+schleuder@tracker.debian.org X-Loop: dispatch@tracker.debian.org X-Distro-Tracker-Keyword: bts X-Distro-Tracker-Package: schleuder List-Id: X-Debian: tracker.debian.org X-Debian-Package: schleuder X-PTS-Package: schleuder X-PTS-Keyword: bts Precedence: list List-Unsubscribe: Control: tag -1 pending Hello, Bug #948981 in schleuder reported by you has been fixed in the Git repository and is awaiting an upload. You can see the commit message below and you can check the diff of the fix at: https://salsa.debian.org/ruby-team/schleuder/commit/aa44bf0766a5b6a38d3784048a7d20a6567c0f75 ------------------------------------------------------------------------ debian/patches: Add patch to handle decryption problems gracefully Handle incoming mails encrypted to an absent key, using symmetric encryption or containing PGP-garbage in a more graceful manner: Don't throw an exception, don't notify (and annoy) the admins, instead inform the sender of the mail how to do better. Closes: #948981 ------------------------------------------------------------------------ (this message was generated automatically) -- Greetings https://bugs.debian.org/948981 schleuder-3.6.0/spec/fixtures/mails/not_bounces/Bug_948982-_marked_as_pending_in_schleuder.eml000066400000000000000000000157731401002544500323320ustar00rootroot00000000000000Received: from immer7-21.glei.ch ([192.168.1.91]) by immer12-24.glei.ch with esmtps (TLSv1.2:ECDHE-RSA-AES256-GCM-SHA384:256) (Exim 4.92) id 1irm4f-0006s8-Nx for team@schleuder.org; Wed, 15 Jan 2020 18:03:21 +0100 Received: from localhost ([127.0.0.1]) by immer7-21.glei.ch with esmtp (Exim 4.92.3) id 1irm4f-0008Vj-Ed for team@schleuder.org; Wed, 15 Jan 2020 18:03:21 +0100 Received: from immer7-21.glei.ch ([127.0.0.1]) by localhost (immer7-21.glei.ch [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 09bs5tCPPwGX for ; Wed, 15 Jan 2020 18:03:17 +0100 Received: from mailly.debian.org ([82.195.75.114]) by immer7-21.glei.ch with esmtps (TLSv1.2:ECDHE-RSA-AES256-GCM-SHA384:256) (Exim 4.92.3) id 1irm4a-0008US-Rr for team@schleuder.org; Wed, 15 Jan 2020 18:03:16 +0100 Received: from ticharich.debian.org ([2607:f8f0:614:1::1274:64]:40220)=0D=0A from C=NA,ST=NA,L=Ankh Morpork,O=Debian SMTP,OU=Debian SMTP CA,CN=ticharich.debian.org,EMAIL=hostmaster@ticharich.debian.org (verified)=0D=0A by mailly.debian.org with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256)=0D=0A (Exim 4.92)=0D=0A (envelope-from )=0D=0A id 1irm4V-0000X2-LU=0D=0A for team@schleuder.org; Wed, 15 Jan 2020 17:03:11 +0000 Received: from localhost ([::1]:49340 helo=ticharich.debian.org) by ticharich.debian.org with esmtp (Exim 4.92) (envelope-from ) id 1irm4U-0008B7-AG for team@schleuder.org; Wed, 15 Jan 2020 17:03:10 +0000 Received: from mailly.debian.org ([2001:41b8:202:deb:6564:a62:52c3:4b72]:51378)=0D=0A from C=NA,ST=NA,L=Ankh Morpork,O=Debian SMTP,OU=Debian SMTP CA,CN=mailly.debian.org,EMAIL=hostmaster@mailly.debian.org (verified)=0D=0A by ticharich.debian.org with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256)=0D=0A (Exim 4.92)=0D=0A (envelope-from )=0D=0A id 1irm4U-0008A5-4f=0D=0A for dispatch+schleuder@tracker.debian.org; Wed, 15 Jan 2020 17:03:10 +0000 Received: from quantz.debian.org ([2607:f8f0:614:1::1274:73]:52758)=0D=0A from C=NA,ST=NA,L=Ankh Morpork,O=Debian SMTP,OU=Debian SMTP CA,CN=quantz.debian.org,EMAIL=hostmaster@quantz.debian.org (verified)=0D=0A by mailly.debian.org with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256)=0D=0A (Exim 4.92)=0D=0A (envelope-from )=0D=0A id 1irm4S-0000Uj-Ki=0D=0A for dispatch+schleuder@tracker.debian.org; Wed, 15 Jan 2020 17:03:08 +0000 Received: from qa by quantz.debian.org with local (Exim 4.92) (envelope-from ) id 1irm4R-0002FA-Ak for dispatch+schleuder@tracker.debian.org; Wed, 15 Jan 2020 17:03:07 +0000 Received: from buxtehude.debian.org ([2607:f8f0:614:1::1274:39]:51074)=0D=0A from C=NA,ST=NA,L=Ankh Morpork,O=Debian SMTP,OU=Debian SMTP CA,CN=buxtehude.debian.org,EMAIL=hostmaster@buxtehude.debian.org (verified)=0D=0A by quantz.debian.org with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256)=0D=0A (Exim 4.92)=0D=0A (envelope-from )=0D=0A id 1irm4R-0002Ee-8i=0D=0A for schleuder@packages.qa.debian.org; Wed, 15 Jan 2020 17:03:07 +0000 Received: from debbugs by buxtehude.debian.org with local (Exim 4.92) (envelope-from ) id 1irm4R-0007bJ-1Z; Wed, 15 Jan 2020 17:03:07 +0000 Received: via spool by 948982-submitter@bugs.debian.org id=U948982.157910757828013 (code U ref 948982); Wed, 15 Jan 2020 17:03:06 +0000 Received: (at 948982-submitter) by bugs.debian.org; Wed, 15 Jan 2020 16:59:38 +0000 Received: from mailly.debian.org ([2001:41b8:202:deb:6564:a62:52c3:4b72]:55086)=0D=0A from C=NA,ST=NA,L=Ankh Morpork,O=Debian SMTP,OU=Debian SMTP CA,CN=mailly.debian.org,EMAIL=hostmaster@mailly.debian.org (verified)=0D=0A by buxtehude.debian.org with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256)=0D=0A (Exim 4.92)=0D=0A (envelope-from )=0D=0A id 1irm14-0007HF-8g=0D=0A for 948982-submitter@bugs.debian.org; Wed, 15 Jan 2020 16:59:38 +0000 Received: from godard.debian.org ([209.87.16.44]:52234)=0D=0A from C=NA,ST=NA,L=Ankh Morpork,O=Debian SMTP,OU=Debian SMTP CA,CN=clientcerts/godard.debian.org,EMAIL=hostmaster@clientcerts/godard.debian.org (verified)=0D=0A by mailly.debian.org with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256)=0D=0A (Exim 4.92)=0D=0A (envelope-from )=0D=0A id 1irm12-0000MV-NP=0D=0A for 948982-submitter@bugs.debian.org; Wed, 15 Jan 2020 16:59:36 +0000 Received: by godard.debian.org (Postfix, from userid 3510) id 44B93A1219; Wed, 15 Jan 2020 16:59:35 +0000 Resent-Date: Wed, 15 Jan 2020 17:03:06 +0000 Resent-From: Debian BTS Resent-To: Georg Faerber Resent-Message-ID: Date: Wed, 15 Jan 2020 16:59:35 +0000 From: Georg Faerber Sender: noreply@salsa.debian.org Reply-To: Georg Faerber , 948982-quiet@bugs.debian.org To: 948982-submitter@bugs.debian.org Message-ID: <5e1f44f73e3af_37683fd3c001e4f083093@godard.mail> References: <20200115151452.GJ26536@debian> Subject: Bug#948982: marked as pending in schleuder Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 7bit X-Virus-Scanned: amavisd-new at glei.ch X-Loop: owner@bugs.debian.org Original-Sender: noreply@salsa.debian.org X-Loop: owner@bugs.debian.org X-Debian-PR-Message: report 948982 X-Debian-PR-Package: schleuder X-Debian-PR-Keywords: fixed-upstream X-Debian-PR-Source: schleuder X-Spam-Bayes: score:0.0000 Tokens: new, 15; hammy, 113; neutral, 25; spammy, 6. spammytokens:0.999-1--H*RT:sk:noreply, 0.993-1--HAuto-Submitted:auto-generated, 0.958-+--H*r:sk:noreply, 0.950-+--H*F:U*noreply, 0.919-+--H*rp:U*noreply hammytokens:0.000-+--sk:salsad, 0.000-+--sk:salsa.d, 0.000-+--UD:salsa.debian.org, 0.000-+--salsadebianorg, 0.000-+--salsa.debian.org Auto-Submitted: auto-generated Delivered-To: schleuder@packages.qa.debian.org Delivered-To: dispatch+schleuder@tracker.debian.org X-Loop: dispatch@tracker.debian.org X-Distro-Tracker-Keyword: bts X-Distro-Tracker-Package: schleuder List-Id: X-Debian: tracker.debian.org X-Debian-Package: schleuder X-PTS-Package: schleuder X-PTS-Keyword: bts Precedence: list List-Unsubscribe: Control: tag -1 pending Hello, Bug #948982 in schleuder reported by you has been fixed in the Git repository and is awaiting an upload. You can see the commit message below and you can check the diff of the fix at: https://salsa.debian.org/ruby-team/schleuder/commit/7418064a3c09ce049a833230d8284fb7243c334e ------------------------------------------------------------------------ debian/patches: Add patch to default to ASCII-8BIT encoding This should ensure Schleuder is able to handle mails with different charsets. Closes: #948982 ------------------------------------------------------------------------ (this message was generated automatically) -- Greetings https://bugs.debian.org/948982 schleuder-3.6.0/spec/fixtures/mails/not_bounces/tt_1234210666.txt.eml000066400000000000000000000037251401002544500250300ustar00rootroot00000000000000From agris.ameriks@accenture.com Mon Feb 9 22:17:46 2009 Return-Path: X-Original-To: ameriks@amerimail.lv Delivered-To: bounce_and_mail_handler@ameriks Received: from ememr1003.accenture.com (ememr1003.accenture.com [170.252.72.95]) by ameriks (Postfix) with ESMTPS id 237A53A08C for ; Mon, 9 Feb 2009 22:17:46 +0200 (EET) Received: from EMEXV1004.dir.svc.accenture.com (emexv1004.dir.svc.accenture.com [10.130.16.107]) by ememr1003.accenture.com (8.13.8/8.13.8) with ESMTP id n19KHQQp012745 for ; Mon, 9 Feb 2009 20:17:43 GMT Received: from emexr1003.dir.svc.accenture.com ([10.130.16.112]) by EMEXV1004.dir.svc.accenture.com with Microsoft SMTPSVC(6.0.3790.1830); Mon, 9 Feb 2009 21:16:34 +0100 Received: from EMEXM0302.dir.svc.accenture.com ([10.130.16.127]) by emexr1003.dir.svc.accenture.com with Microsoft SMTPSVC(6.0.3790.1830); Mon, 9 Feb 2009 21:16:38 +0100 X-MimeOLE: Produced By Microsoft MimeOLE V6.00.3790.3168 Content-class: urn:content-classes:message MIME-Version: 1.0 Importance: normal Priority: normal Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: quoted-printable Subject: Arpus biroja atrasanas automatiska atbilde: subjecting Date: Mon, 9 Feb 2009 21:16:32 +0100 Message-ID: X-MS-Has-Attach: X-MS-TNEF-Correlator: Thread-Topic: subjecting Thread-Index: AcmK80zS8L6DgfKxTMON80Obs/ge4QAAAAOa From: To: X-OriginalArrivalTime: 09 Feb 2009 20:16:38.0386 (UTC) FILETIME=[50313D20:01C98AF3] Thank you for your email. I am out of office and will be back on Tuesday 9:00. This message is for the designated recipient only and may contain = privileged, proprietary, or otherwise private information. If you have = received it in error, please notify the sender immediately and delete = the original. Any other use of the email by you is prohibited. schleuder-3.6.0/spec/fixtures/mails/not_bounces/tt_1234211024.txt.eml000066400000000000000000000042301401002544500250050ustar00rootroot00000000000000From MAILER-DAEMON Mon Feb 9 22:23:44 2009 Return-Path: <> X-Original-To: bounces-main+agris.ameriks=gmail.com@amerimail.lv Delivered-To: bounce_and_mail_handler@ameriks Received: from mail-bw0-f164.google.com (mail-bw0-f164.google.com [209.85.218.164]) by ameriks (Postfix) with ESMTP id 1F0A13A08C for ; Mon, 9 Feb 2009 22:23:44 +0200 (EET) Received: by bwz8 with SMTP id 8so2417119bwz.4 for ; Mon, 09 Feb 2009 12:23:43 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:received:message-id:date:from:to:subject :mime-version:content-type:content-transfer-encoding :content-disposition:precedence:x-autoreply; bh=N1fY4J/R56Y76WNR/I9bQfBBxJb49OKIxsGFWNKUWVY=; b=drTotfyYsI7Vhh+BvIhvVQY8uI3KoDNsYyidJ74rEYVsC/AizeWH6KkNdzbtyn4DXl d9qm2tzYGTZk7oRA1IDQWG8iGFfJKtz5d9JPLD9StGsQhZ+mTne0m32hqsMKxcG+1TE7 DcqUJJ7lqMsoWIm9/qfrKh4M9WpYg+EsR1np0= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=message-id:date:from:to:subject:mime-version:content-type :content-transfer-encoding:content-disposition:precedence :x-autoreply; b=Tq6LsLhors0+QfBe4baI1UEuuMm2RwJVE1WJS6i2qaPn557zNbnRYQfrv9m2hb93Ks /2GIjkIa+GT0QN9WIY9qCywiojBtznRT8hjk5C3OibuZdGMjCQn1l2lA8xgEG8jcdMGR Cir8us4vyOqUQjhQ6Vl/m/6FwENpgU8/H1YIk= Received: by 10.181.218.14 with SMTP id v14mr357446bkq.48.1234211023205; Mon, 09 Feb 2009 12:23:43 -0800 (PST) Message-ID: Date: Mon, 9 Feb 2009 12:23:43 -0800 From: "Agris Ameriks" To: bounces-main+agris.ameriks=gmail.com@amerimail.lv Subject: =?ISO-8859-13?Q?Atvalin=E2jums_Re:_subjecting?= MIME-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-13 Content-Transfer-Encoding: base64 Content-Disposition: inline Precedence: bulk X-Autoreply: yes RXNtdSBhdHZh72lu4mp1beIKCi0tIAotLS0tLS0tLS0tCldpdGggcmVnYXJkLApBZ3JpcyBBbWVy aWtzClBob25lICszNzEgMiA2NDYxMTAxCkUtbWFpbDogQWdyaXMuQW1lcmlrc0BnbWFpbC5jb20K schleuder-3.6.0/spec/fixtures/mails/not_bounces/tt_1234241664.txt.eml000066400000000000000000000020741401002544500250260ustar00rootroot00000000000000From bounces-main+bratchka=amerimail.lv@amerimail.lv Tue Feb 10 06:54:24 2009 Return-Path: X-Original-To: bratchka@amerimail.lv Delivered-To: bounce_and_mail_handler@ameriks Received: from Albanis-3.local (unknown [87.99.72.11]) by ameriks (Postfix) with ESMTP id 3499D3A08C for ; Tue, 10 Feb 2009 06:54:24 +0200 (EET) Received: by Albanis-3.local (Postfix, from userid 501) id D9FB832925D; Tue, 10 Feb 2009 06:54:22 +0200 (EET) Date: Tue, 10 Feb 2009 06:54:14 +0200 From: ameriks@amerimail.lv Reply-To: ginta.amerika@ameri.lv To: bratchka@amerimail.lv Subject: Mes loti atvainojamies, ja sanemat so epastu Mime-Version: 1.0 Content-Type: text/html; charset=utf-8 Message-Id: <20090210045423.D9FB832925D@Albanis-3.local> Labdien, mes loti atvainojamies, ja sanemat so epastu. Mes paslaik veicam jaunas sistemas izstradi, kur ir arii ieklauta epastu sutisana. Ludzu ignorejiet so e-pastu! Paldies par sapratni. Ja jus velaties ar mums sazinaties si epasta sakaraa, sutiet epastu uz agris.ameriks@ameri.lv. schleuder-3.6.0/spec/fixtures/mails/plain/000077500000000000000000000000001401002544500205045ustar00rootroot00000000000000schleuder-3.6.0/spec/fixtures/mails/plain/thunderbird.eml000066400000000000000000000055771401002544500235330ustar00rootroot00000000000000Return-Path: Delivered-To: n.siessegger@zeromail.org Received: from smtpin.nadir.org (smtpin.nadir.org [217.114.68.218]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by snail.zeromail.org (Postfix) with ESMTPS id D7C8EC001D for ; Tue, 27 Dec 2016 17:18:59 +0100 (CET) Received: from localhost (localhost [127.0.0.1]) by smtpin.nadir.org (Postfix) with ESMTP id AB2BDE60C1 for ; Tue, 27 Dec 2016 17:18:59 +0100 (CET) Received: from smtpin.nadir.org ([127.0.0.1]) by localhost (smtpin-na.nadir.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id GbNqpozJuesw for ; Tue, 27 Dec 2016 17:18:57 +0100 (CET) Received: from mout.web.de (mout.web.de [212.227.15.4]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtpin.nadir.org (Postfix) with ESMTPS id A91EAE604F for ; Tue, 27 Dec 2016 17:18:57 +0100 (CET) Received: from nna.local ([80.187.107.60]) by smtp.web.de (mrweb004 [213.165.67.108]) with ESMTPSA (Nemesis) id 0McT8i-1c4NZw3xE8-00Hgam for ; Tue, 27 Dec 2016 17:18:57 +0100 To: n.siessegger@zeromail.org From: Nina Siessegger Subject: Test Message-ID: <8db04406-e2ab-fd06-d4c5-c19b5765c52b@web.de> Date: Tue, 27 Dec 2016 17:18:57 +0100 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.12; rv:45.0) Gecko/20100101 Thunderbird/45.5.1 MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 7bit X-Provags-ID: V03:K0:q07lv8kyV5vZ2Bkz3y99DthdSlg2NU0SQbMMZtb6PkyKzuO3TqS O2/qixJf4THt+J1OEiMuWOG71sYXBENA7fUZzy25Xy3mpDLgOJj55qE8+KOFuLfWPyb2OeI 39NYZ0+mLzIuJEiq4JnfYnF7s1SN5jv3CadFuO206MV7recIxXOjpxHPDvoyfzLMyxqRb5b jM6SATIl6pRdymPUNFsjQ== X-UI-Out-Filterresults: notjunk:1;V01:K0:9gbmm2iZtw4=:psOpZ/aY5zv6agYRXPOnce fJ6S+HVb03oKnQICo4EZZxwCuxBpd1xUHzJFid+KUGgvVNXPwpi5Z0hg57WQQYwhopWhY2eCm o9nJ6xMVS8CV8uX0lEXsoNM/JRt5oM1OvIIQuuuAzUDw7F1nnmGQPOMleAMAQ7GyvfirSZfx4 VrLOsF0vIZJOwoP5rZusgqrCteOJn5TC+Wy5UDb0w3ogzJQRsNLTN2Q6f5b7mzuT1zEVPdpU2 HMHvoRTVQpMYtfTjoVJlVKfh5Zf6eurPDFa980+/h5xQKf0+W+u1Z1JCe8zI45628TPPzQNN9 VvugURsiPDP3h3zxj/joo6O2l4Vk/30Mxr7k+PVhSLno4GNjS5oL52o+AG0ZRjD3fKWrnArXr j0emey1AI1EZij+FwwWyf0JF7ubRvN2qXRovU+ZYZ3fV1x56S5ZXdiuOqImHzgYcCdKQ1Mbj3 HX+jleuL6Gkgv2hdHcq++zErqiSbBhJKxPfDGAIwRpb/kAf3/sEGGhdLAlzlagXbbNgScVNsa PQIRuXvDim+eTk8Wb0Wh17flIzpgtz/bU8ZA61WLN8yt1v3aGevuwbMbO75dO/QOU4s4Yaaln 2LUsTYwtLKuqOY+reg6J3dZYyRwMTIl8961GcGXI3xHyHlKORKPk36b0/H0kHRi337qNl5mKF Z4WiQdpohcsGg0plEuZRLdxJ7knXQX3kZxO2FlTAhfPdWN1MDuQ+CiWi8MRwApOTQeR0nzRuR 2RAcnGeDuEgC3L/e6jkVJTvg45eulIeiIQPtEmx7eC3xs+wnifTCXqI4Mi9SDWtQxnPmWPPrh QAox8QKjkrSq/JyqvmWV7fCOJur8Wmms+oyr8g/MpOBqTMGbZumCNBa4UaGnSDTFon8Qg8djv c4C7eaiiU7Z6bS9xU/qA== Test schleuder-3.6.0/spec/fixtures/mails/protected-headers-request.eml000066400000000000000000000061451401002544500251760ustar00rootroot00000000000000From - Fri Sep 29 10:33:00 2017 Subject: Encrypted Message From: paz To: schleuder-request@example.org Message-ID: Date: Fri, 29 Sep 2017 10:33:00 +0200 MIME-Version: 1.0 Content-Type: multipart/encrypted; protocol="application/pgp-encrypted"; boundary="NNqdAeeD0BMoMnLVbGvlJ93USlrgv66Hi" This is an OpenPGP/MIME encrypted message (RFC 4880 and 3156) --NNqdAeeD0BMoMnLVbGvlJ93USlrgv66Hi Content-Type: application/pgp-encrypted Content-Description: PGP/MIME version identification Version: 1 --NNqdAeeD0BMoMnLVbGvlJ93USlrgv66Hi Content-Type: application/octet-stream; name="encrypted.asc" Content-Description: OpenPGP encrypted message Content-Disposition: inline; filename="encrypted.asc" -----BEGIN PGP MESSAGE----- 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 QO+1dOvJpclKws4ZKEkZcAjxKCd+DPjodK4= =msZE -----END PGP MESSAGE----- --NNqdAeeD0BMoMnLVbGvlJ93USlrgv66Hi-- schleuder-3.6.0/spec/fixtures/mails/protected-headers.eml000066400000000000000000000043021401002544500235010ustar00rootroot00000000000000From - Fri Sep 29 10:33:00 2017 Subject: Encrypted Message From: paz To: schleuder@example.org Message-ID: Date: Fri, 29 Sep 2017 10:33:00 +0200 MIME-Version: 1.0 Content-Type: multipart/encrypted; protocol="application/pgp-encrypted"; boundary="NNqdAeeD0BMoMnLVbGvlJ93USlrgv66Hi" This is an OpenPGP/MIME encrypted message (RFC 4880 and 3156) --NNqdAeeD0BMoMnLVbGvlJ93USlrgv66Hi Content-Type: application/pgp-encrypted Content-Description: PGP/MIME version identification Version: 1 --NNqdAeeD0BMoMnLVbGvlJ93USlrgv66Hi Content-Type: application/octet-stream; name="encrypted.asc" Content-Description: OpenPGP encrypted message Content-Disposition: inline; filename="encrypted.asc" -----BEGIN PGP MESSAGE----- hQIMA691X8Gl2MArAQ/9EkuJLshPrMOSe38BjyUBe+1L2hUQOxBd0MI0d/C0Yadj 7YtlwveeqTpLGuT7H+ecaVlhMC9KFL4NT8v64D2e4S68wymVHUqO8SezMW8Bp5ut 2psZb+/KqF7oKLkkOu6neKo8PODrDcPK5pQGBBdV9DP2Z7uNfSyTJvVfNsf/3Q7e mpQAgj9g2uooMPSqNRhOOrLPL6uWPIkfcvnt1gb4eG++ltpBD243yRxnUFrUxghq rVH6V1la0d/WO3sLOu3oVAC71NPNq5DilVFfKl+/H5BwK54pmmuvu05JKgZw1QqJ lImWRFv8GPmeyvqu9F0A4E0e4aFIly5/uHrBq0uw7R/gmeUICcwb28/ZftPj2ZEr O9C0flYVwWB3cor5owM0rOtcgbwBI6EvSQ1d51qNA1PnpIu7woptFl10tguBiJ5X HmrK+nOaXy1Rf/clrrmd/BeLtuXheb+N6WpWgiwV1MSZqP8IFBYq7R/STQpWyhxO qmMGx27iJmTHx1nQpfzZybiecws1oOHY/gOc7uI1I4+zfitdRBsOozQDB8K8lEjK 3lsDmQoCu8GUQJj6t6OGn5YlEQ+oSGNc189sDThgGG5KDVGqd5OoI0ckxWam1GeR b40imecyWm5v2aejOaHisK463YsUSO8HsIUDEtCllvl4gF1dxeUvflWKSNqqwrPS wS4BC3VdOj2RY6vxtTBpfWLqLqsMQ970wXV9oKCLSrbobgJSwUleU3I1WGhXegDI hBxRFvYIDr3R6OTDnbGTnB7We//mk5GN5eXAMs5o7Zqcn54Mox471x8Veg1dUoj2 2c6/Vgg5yX1cy+5SaZGSYDeKbyx2PSoMXZZWQHQ+KPe527gLAzpoeUAWN1H+lU6y eORjBBlk/GQF15r5BmytQraTqsJTRG22SpycpYNugzgJPzozdjXGZ5Vdz9UHo3FC Ch6gNXjeDXNCJ8PRQr3LQKrIsT6nE7zmF0N69LwJfMSm5MYIJnkhJ5tzJ/7MmcUr OfgVkorhjM2oz4w8imI+2xFy4LhOKYEr0JHBN8X5QZ5yYQ2CVPDX3MwvpW0qn5PH iQSC99Kabne9rmCByx7Ue+WUCZkuTJq201U0iSf2gNu2e8ebz+Y0ZxJ7JgH1eqyU MLfSxyFry3JQ84zHgIFJV6EPmk4W+JhsdoPGTYghsUYpBaGsn/e1JPhpn3+mQnPV +KH+x2ES9EmSMmHYBV5RY7YQB31hqnazY+omqSCgZotBq18/jHg2fnzEtvzj0fEr PgMyC/zUcSTWknToRhU7dVFzYs19/1vnJJthAQxH7Zbx5kfisYVMcyh2OSEpaPH/ C1d7wjZUT2goLpGaDYK+xQ== =u70c -----END PGP MESSAGE----- --NNqdAeeD0BMoMnLVbGvlJ93USlrgv66Hi-- schleuder-3.6.0/spec/fixtures/mails/qp-encoding-clear.eml000066400000000000000000000012401401002544500233650ustar00rootroot00000000000000Date: Tue, 11 Jul 2017 12:00:40 +0200 From: test@localhost To: schleuder@example.org Subject: Input Test QP encoding broken Message-ID: <20170711100040.GF7104@blabla> MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Disposition: inline Content-Transfer-Encoding: quoted-printable On 17-07-11 11:59:56, schleuder@nadir.org wrote: > From: foo > To: schleuder@example.org > Cc:=20 > Date: Tue, 11 Jul 2017 11:59:49 +0200 > Sig: Good signature from somethingsomething > Enc: Encrypted > foo foo foo > foo foo foo > foo foo foo >=20 > [1] https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=3D867031 https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=3D867031 schleuder-3.6.0/spec/fixtures/mails/qp-encoding-encrypted+signed.eml000066400000000000000000000061621401002544500255510ustar00rootroot00000000000000From: test@localhost Subject: something To: schleuder@example.org Message-ID: <381fb765-1e53-4578-bc93-bff7e689cbaa@example.org> Date: Fri, 21 Jul 2017 11:50:35 +0200 MIME-Version: 1.0 Content-Type: multipart/encrypted; protocol="application/pgp-encrypted"; boundary="OguUqTN7k1TEvsvAHoUI3Hv5qStt1SOH3" This is an OpenPGP/MIME encrypted message (RFC 4880 and 3156) --OguUqTN7k1TEvsvAHoUI3Hv5qStt1SOH3 Content-Type: application/pgp-encrypted Content-Description: PGP/MIME version identification Version: 1 --OguUqTN7k1TEvsvAHoUI3Hv5qStt1SOH3 Content-Type: application/octet-stream; name="encrypted.asc" Content-Description: OpenPGP encrypted message Content-Disposition: inline; filename="encrypted.asc" -----BEGIN PGP MESSAGE----- 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 Xe7gviDKl62tMcXuN8d5E0RUeVdCGEaSQQy7 =QAIj -----END PGP MESSAGE----- --OguUqTN7k1TEvsvAHoUI3Hv5qStt1SOH3-- schleuder-3.6.0/spec/fixtures/mails/qp-encoding-encrypted.eml000066400000000000000000000034711401002544500243040ustar00rootroot00000000000000Date: Tue, 11 Jul 2017 12:00:40 +0200 From: test@localhost To: schleuder@example.org Subject: Input Test QP encoding broken encrypted Message-ID: <20170711100040.GF7104@blabla> MIME-Version: 1.0 Content-Type: multipart/encrypted; protocol="application/pgp-encrypted"; boundary="4f28nU6agdXSinmL" Content-Disposition: inline --4f28nU6agdXSinmL Content-Type: application/pgp-encrypted Content-Disposition: attachment Version: 1 --4f28nU6agdXSinmL Content-Type: application/octet-stream Content-Disposition: attachment; filename="msg.asc" -----BEGIN PGP MESSAGE----- hQIMA691X8Gl2MArARAAreFTl/Yz+V0YBDfl54Zz+S3rENPDKXEmNJNzcYoLIEuH beoeWMHY9nzD7QkaNaeNL3foK9gr62njvrf6KsQVgnoUE8cQFhk2FJkPoylWGAnT 2zI/dZLpMit/J3WSG1U02C/lOXN7M1kuvx7O/tGiKRtudyCwGO+qrAp/BCEIwBDz sJcEo9HAU4odV1oPFGDDw+y+EfOmTj+afplsSft0hDmI+hWnkjaWKCxhmR5BEWr2 fBkaAzH4rMls8g22llZrL3Rens4UT/htOMiDXoxBQ4oE3P+sb8WesmpSJwU77y3J 7DBdwBfI0q4kI3EjOBMvOQPLCYZl5+3LckQRl5QGPaBC+BaeAsXS2dEPRl5Xw1Ae ZzxTgusV7V0hDhNG3z3SzmczfUZ7+6OQ7HsOhHAVa3KmuWpaw8Dr5s2n6AhzZNGs A8HmWQETa9DxGQTKrcijB5LyIFTo8d5Hc144En9demO0ApBd3Jg5lhkAr+vAL/z0 OkL35vosRWMncHx2GB6ido7IoMz4zXiKW34ezXJWvH5SwRdjOuy6WMvOzGToxJcn fK55f/xoq63N/uhHuVy8BH56AjI5OAfEowZ1jb/pGGRGM36JwrdwInbwSMU/X34r 6ERESKrDqRvk27u0C10iAMFMfIdQVlfJN+kKXxyKDxOaukbSexnaFBNyi07b7DzS wLUBqDDjF8zXjCQNvOlqcBrVht3e0H4YqUFPfXy+fuGYL6FWobjuUDN9ZYbcuDwu w6ioBRoFmUwvOzTI9S40+JDR8RcFPbZuYYzBEZnqNJapsy7XrvXQUXlmOB7klm0s 4m/d5edXlp93KqbO+oJ05Bse88cXvfDIrRKkV+YSWOB9VxAES3SK79QQRYlJlEdn zzcmSt8ODewc6WfO93u0gG/2xCftEHpi/iHFlgrzSVuZMa0Vn5AXva819aJ3t9D7 OYKEp2IARQHSB30W7iIOK/cyS6ymE27137uETNQ7FinES9929E9WCd+3vk/lSZLr DnhSuGSNRV36srVsN7SkbbrvfF6iipJDC3Y1GQVmngpu6nU1r0/koqGkeIJr7Sao mGIgpVBBZYbhS3LBw6h87gtYEbKirwNLuP+WHY2uQkLIBCv7/ugrATHn503nwwEp GNFu+Bhh6FQZhMfgIlSHpV5jsHeMQFqy/xgW5VgnWhqZAEEKW1AA =IB9S -----END PGP MESSAGE----- --4f28nU6agdXSinmL-- schleuder-3.6.0/spec/fixtures/mails/signed-inline/000077500000000000000000000000001401002544500221265ustar00rootroot00000000000000schleuder-3.6.0/spec/fixtures/mails/signed-inline/thunderbird.eml000066400000000000000000000027501401002544500251430ustar00rootroot00000000000000Received: from [IPv6:::1] (localhost.localdomain [IPv6:::1]) by flutsch.local (Postfix) with ESMTP id 777D3801DD for ; Thu, 29 Dec 2016 15:21:42 +0100 (CET) To: schleuder@example.org From: paz Subject: signed-inline Openpgp: id=52507B0163A8D9F0094FFE03B1A36F08069E55DE Message-ID: Date: Thu, 29 Dec 2016 15:21:42 +0100 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Thunderbird/45.5.1 MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit -----BEGIN PGP SIGNED MESSAGE----- Hash: SHA512 This is a test. Umlauts: öäß. ♥★ -----BEGIN PGP SIGNATURE----- iQIzBAEBCgAdFiEEUlB7AWOo2fAJT/4DsaNvCAaeVd4FAlhlG/YACgkQsaNvCAae Vd4g5A/+Joc1sst26EGHhYL/MrYICBljcvFHWYHo81sr6ED1ek18eWiHtHGFhWvO HyJ0Ccu1ktdcyay7K70gpRNrjvs2d3l5sAAfgMyDPsvBrvWHKYUpiypcVG/7FRrD 1RVsQroh4xTo2wzWOjn47dT0EMhVZtg4jITSQn25dj8/D9viUeE3fiGFLtG5KLhU B1l+3A5cYrzaSRy9p6VoCPSEOCToZ34LJd9RkG/QKMD9JT/HcZN89sRVL0e4qI8e wQWsI6Oi7WNGiUA+p8Q5un90KNCqqumjkVxIiiFk5wSB4egba6JIBW43pKYrklRz wIXrNCk/RWcPJMTqIH9n+2IrDlKeYO/u+h/uh1y0SOTnImkmpfcgYsG3ggPnVask T2J8CCQ5Xy0HecyEFt5GO9pYG73vG9bX/YQ3cGN6yUJxmXzlQ02iS6UVx5g8Ypy2 NuZwQKFUGUeFta2mRlkKn8VZfqXrWv3VtKoaa1Zm0gZydTDA/37W5A2xrGk9IvjZ CUGx4jLqXbOFJ+zOthI9JJmaPP4sc7hUmegAjV1PJP6AaIZ+6TLwn+gY1z7SaRd2 59bA6Bnm4S7p8nV7oPwW/WaOUu3mF7y5w4Yd8DAS5BKC5UiBexrhY6mH71jXb+J9 VZOIwSEI9QvBKQM/7wULApVGq1kPR3K6XKAMvWiez3ayqsYUflk= =TSUJ -----END PGP SIGNATURE----- schleuder-3.6.0/spec/fixtures/mails/signed-mime/000077500000000000000000000000001401002544500215775ustar00rootroot00000000000000schleuder-3.6.0/spec/fixtures/mails/signed-mime/thunderbird.eml000066400000000000000000000043651401002544500246200ustar00rootroot00000000000000Received: from [IPv6:::1] (localhost.localdomain [IPv6:::1]) by flutsch.local (Postfix) with ESMTP id E276680329 for ; Thu, 29 Dec 2016 15:14:42 +0100 (CET) To: schleuder@example.org From: paz Subject: signed-mime test Openpgp: id=52507B0163A8D9F0094FFE03B1A36F08069E55DE Message-ID: Date: Thu, 29 Dec 2016 15:14:42 +0100 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Thunderbird/45.5.1 MIME-Version: 1.0 Content-Type: multipart/signed; micalg=pgp-sha512; protocol="application/pgp-signature"; boundary="DnUG3PvpPDcqa5kwpXHvXR1RjOgf17M3b" This is an OpenPGP/MIME signed message (RFC 4880 and 3156) --DnUG3PvpPDcqa5kwpXHvXR1RjOgf17M3b Content-Type: multipart/mixed; boundary="L98FCUdRgUPMMRg5CUqPXDjjv0kGAXPf0"; protected-headers="v1" From: paz To: schleuder@example.org Message-ID: Subject: signed-mime test --L98FCUdRgUPMMRg5CUqPXDjjv0kGAXPf0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable This is a test Umlauts: =C3=B6=C3=A4=C3=9F =E2=99=A5=E2=98=85 --L98FCUdRgUPMMRg5CUqPXDjjv0kGAXPf0-- --DnUG3PvpPDcqa5kwpXHvXR1RjOgf17M3b Content-Type: application/pgp-signature; name="signature.asc" Content-Description: OpenPGP digital signature Content-Disposition: attachment; filename="signature.asc" -----BEGIN PGP SIGNATURE----- iQIzBAEBCgAdFiEEUlB7AWOo2fAJT/4DsaNvCAaeVd4FAlhlGlIACgkQsaNvCAae Vd5VQQ/7BfL7kQA30QfQMoOLqnww/jX2aCeOIAisuPE0CU1oqxn00ntSIl7vMYIl Gu16gfwXrftbNxLfEwlLN6xZbzPJg+JefumOZglAqP9zHONxuwhO3QkaN0+K2Gfl ECDVAOxVZX52APoFkkgJjkUcHmCa2GeFROhgmDtCxeGjBTQlRg6WNu+xeJmR9GUG MQSaaMxHHSFxTmXQonRa5C1ATw9ZXekDOHK8LEO5hq04WEus0zio0a6fi+/xgTUS rJb+9el+pSOa9pZ5ZFfWWqFYuG5d4GNQpNeZQZjnUKKt0PvSw8g6Sqe0UvAeyjyg HRjDAsCijMaMql4+w6Ko7T8vl/C2By0bBeJfpZ1YkR+wa28+v2u3G8l2Mk7azkzT a8QHMzyTITv3D3MunpXSrp6Blh9X2u5PmkD9BkxHduuz/J7kgvufini8oqc3WP4U zZ8ZfU3ruon2le4UCRE/kWtDgCEK8+ppYqF/GSJZ6j1lO+tOfuWjwhotdtdG88/x bRS2GXecp7Jy8aosC0c0MHqZEMRUCKfN9lQLFf3oi+7f1AhDZbTzVnI+KGduZU3h /gk3kwLHFUd2epIjiWOygQyfpMQCqNvaskz8md3uH9P2F1mfHi1CaUB5Nq1gLegP GNmgErDQLDCoBnEW3aNsEM/BzPy2JRMi9k/sPXQ0GsTZhH62MV0= =CSzt -----END PGP SIGNATURE----- --DnUG3PvpPDcqa5kwpXHvXR1RjOgf17M3b-- schleuder-3.6.0/spec/fixtures/more_filters/000077500000000000000000000000001401002544500207665ustar00rootroot00000000000000schleuder-3.6.0/spec/fixtures/more_filters/pre_decryption/000077500000000000000000000000001401002544500240145ustar00rootroot00000000000000schleuder-3.6.0/spec/fixtures/more_filters/pre_decryption/166_late_example.rb000066400000000000000000000001111401002544500273660ustar00rootroot00000000000000module Schleuder::Filters def self.late_example(list, mail) end end schleuder-3.6.0/spec/fixtures/more_filters/pre_decryption/25_example.rb000066400000000000000000000001041401002544500262750ustar00rootroot00000000000000module Schleuder::Filters def self.example(list, mail) end end schleuder-3.6.0/spec/fixtures/more_filters/pre_decryption/6_early_example.rb000066400000000000000000000001121401002544500274070ustar00rootroot00000000000000module Schleuder::Filters def self.early_example(list, mail) end end schleuder-3.6.0/spec/fixtures/mutt_protected_headers.txt000066400000000000000000000033621401002544500235760ustar00rootroot00000000000000From schleuder@example.org Thu Jun 13 15:19:33 2019 Received: from 127.0.0.1 (helo=localhost.localdomain) by mail.example.com with esmtpsa (TLSv1.2:ECDHE-RSA-AES256-GCM-SHA384:256) (Exim 4.92) id 1hbPdc-0007GN-6b for schleuder@example.org; Thu, 13 Jun 2019 15:19:32 +0200 Date: Thu, 13 Jun 2019 15:19:30 +0200 From: dev To: schleuder@example.org Subject: ... Message-ID: <20190613131930.ABC@xyz> MIME-Version: 1.0 Content-Type: multipart/encrypted; protocol="application/pgp-encrypted"; boundary="z6Eq5LdranGa6ru8" Content-Disposition: inline --z6Eq5LdranGa6ru8 Content-Type: application/pgp-encrypted Content-Disposition: attachment Version: 1 --z6Eq5LdranGa6ru8 Content-Type: application/octet-stream Content-Disposition: attachment; filename="msg.asc" -----BEGIN PGP MESSAGE----- hQIMA691X8Gl2MArAQ//SFZyc/TD/9PYMddJcUIp4F85wsoCUZUaVLpKBzUZdrLv rln9bgaou4MiUXF8ZTSqq2ET6A3X7+wpDjs79KiDJnILUmguGDT2KTkyD8lxP9nd oIKtqKdf95AYGmItYkaQqdZf1No2q4ZBQNWXp8+LZgxINn5AW+9wuOo8F9w+tyZJ 8r9jlj5TJ0YnVp5FieKMMyxiSOCGX8lAaqi4TbML35OWrnL8Decsz5tTX4jfqr8L cvNuIpa863WkbZxMxLEEn4/yC6upmOnU3eSZ9M/UoXiqgBsd01KEoOvmIIPOgGce IaCxO4zuoPvtcQsuinlLCI2oX9mpex6iTMGmD1J0G9FNGI3OHkwZcahw+4/3dv9K jfUjm6XwndtYi6ifAPAf8M8RT84hFlZKqR7IpGmpqWnLZx6BcFV0RDu8GCIPD6Fr UeLu1hGLD3SMbKy9zSR4lDSkMRvCUumXAebtEvfp7dfQ9Z8I866J5/9EZIDH88M1 Rb9agaBlwwr8Oy0hzC3rwvLyqXi1KD79f+YmGL0yatYPTm37qCE+QdfXCkesN6jg SV3zjtpBalP0KMCtAhouFf6xDz615nWvC5NRh2yzYOhSVfmZEVrB9Zz7GZx8rsMi 2U0ALYJIc6EI0uc/sLZ9dYu6hBa72VmSe90zS5IE2ZYB24GnzXV95iMsvH35/4vS igFWNQmHxWc9GfwgXN2/P2k4zokCxywLLhoa5xoy+SGmipz2pU8IS4chGT6H5edU /CdBAAdHw7eNgXkuctH9eAM7WE/yu+1tmAPUvzr3ojFyXF+L8d8gcCbOJA4scHb6 /L8B0J+CZG/dkMDxU/xjyc7zz8not13HTr6xklMUIam/OzM95YFmleAN4g== =l547 -----END PGP MESSAGE----- --z6Eq5LdranGa6ru8-- schleuder-3.6.0/spec/fixtures/olduid_key.txt000066400000000000000000000033051401002544500211660ustar00rootroot00000000000000-----BEGIN PGP PUBLIC KEY BLOCK----- mQENBFjWeYkBCADfzR16dDh1o+kYN1OzxDrKw+/DYvxpwggfgZ0nAZkdwM+oHpLB lRfKgfs1lghuMpff/DbTM0xiFUtqPACDrpf9sQ1VS0Z2zCfERy0SITZisBVAtwmg 551MSCBY/g2PWy455r20hcSJSuFLt+Dw8u/y5WNeDpnA7seXvPXs7JrXwwJEi/Ql XZK+1d9AgzQAlFhL2fvvOrAV4NM6JvMy7kpRScTt+szMiGLf+kfiYYlj58xdkhPJ AqU9g0qDnp6Ia7sgaU0Hgs4IWymM6sLrOjtQJI+2/MOx++FK0SpfLW84q++ANw6F dHmYAcXZ3C1iL6YZzkKTLJhwdpupekLxBdynABEBAAG0GW9sZCB1aWQgPG9sZEBl eGFtcGxlLm9yZz6JAU4EEwEKADgCGwMFCwkIBwMFFQoJCAsFFgIDAQACHgECF4AW IQRu5R14/Qsz3mXM9p0hBOIOIIifZgUCWNZ5vwAKCRAhBOIOIIifZj5DCACizhev n/X/oloddPeYfAElO+KBf2Dx9XYRuEoJNb+w5pkwAbcvOKoSVQGPSwUw1IFHr7w4 WjfNRzDm8iBqPUc6jBEwAH9s+LN0rIcr2rDYtXkMZpCgfczPmVoDmMoFn7abnNZc XLMqtk3raRaWeYfzggveyGkUAdPx34N0R6MykZtIQaqnTxel1Htj/XeERfNwmIhX CrBaKsVWYncllPzulupv6xe1hBHlENXc2XEoUqphxJtQEkDGwPPXe5Rb/K7XyJh6 uuXgFWL5cT8OxYt6O8XRZIhdT80kLqLf9WkHQYBHYvMlstzcQYG33f16NIMuj1Ra ern2KdEzIwBCyMsxuQENBFjWeYkBCAD4HsM1gZ8UPtEOFWaUrFnEJLopS+B1iTBS ISdXV0tjQEnplr8Os8LPd2Y6niLYRt7+r0E2CFrZvZ6D9ZVnvK4ex10MnmEqLfgW eK6rssUONptCA46AzCYyGKLXjPzl2R+jtEfJIw3PugN8rSKx4ZFA1h6sPP7NCve6 taICeFtPB4NYT9WLdegoBCVMaRNBqatZv9t11Oq6j874H41ppQnyZ69C3PygGHUe rwx6sREis74QFHVuW10sm44buuGBnAV1vmiYK15s/ByZpcZdIaTljF31vZtIEJbb 9tKDvuSWKLlji3Ao72hn3bWdfOoZPenB8b0VPdteUAgDg4aXxeIjABEBAAGJATYE GAEKACACGwwWIQRu5R14/Qsz3mXM9p0hBOIOIIifZgUCWNZ50gAKCRAhBOIOIIif Zk1JCADbemG0mChBv3TVWZAMFuoqK7vXbDZ3bsJyxUFNeDs49BYO/h3iBbT8nCny bnCzIP0EcCMaZr5629b50fblQhEgndzvgvDOv3RfxUNcbw2SunpS4u2Q3c8TD4ps av1LzfzV+9ha2m1vNJHsKzcoWALNFz2a9KcKuvjvY/8NalsueVbMKgSjVaSLwvEj 9HldIjeeHy2OFMqIjk+DomdVrmcJ4J3ERGrIrq32O7zwWM2iDwx+EXMI2XEvqbbr WfHgGnmNBGJJC4Rs+kQB+PsMeaANXVLvdnX4aC/OAfZBB1UCxI2UFtKtxp3B+eJN TL561iNgOgEG8UAfKyReEwOUM81S =LUmS -----END PGP PUBLIC KEY BLOCK----- schleuder-3.6.0/spec/fixtures/olduid_key_with_newuid.txt000066400000000000000000000042651401002544500236020ustar00rootroot00000000000000-----BEGIN PGP PUBLIC KEY BLOCK----- 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 Ug== =8V6x -----END PGP PUBLIC KEY BLOCK----- schleuder-3.6.0/spec/fixtures/openpgp-keys/000077500000000000000000000000001401002544500207155ustar00rootroot00000000000000schleuder-3.6.0/spec/fixtures/openpgp-keys/public-key-with-third-party-signature.txt000066400000000000000000000045741401002544500307510ustar00rootroot00000000000000-----BEGIN PGP PUBLIC KEY BLOCK----- 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 QKfPPOk= =EqIC -----END PGP PUBLIC KEY BLOCK----- schleuder-3.6.0/spec/fixtures/openpgpkey_52507B0163A8D9F0094FFE03B1A36F08069E55DE.asc000066400000000000000000000061131401002544500256630ustar00rootroot00000000000000-----BEGIN PGP PUBLIC KEY BLOCK----- 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 nyRAUuvGT7Lx =wHia -----END PGP PUBLIC KEY BLOCK----- schleuder-3.6.0/spec/fixtures/partially_expired_key.txt000066400000000000000000000041271401002544500234320ustar00rootroot00000000000000-----BEGIN PGP PUBLIC KEY BLOCK----- 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 =xAyq -----END PGP PUBLIC KEY BLOCK----- schleuder-3.6.0/spec/fixtures/revoked_key.txt000066400000000000000000000035641401002544500213540ustar00rootroot00000000000000-----BEGIN PGP PUBLIC KEY BLOCK----- mQGiBEjVO7oRBADQvT6wtD2IzzIiK0NbrcilCKCp4MWb8cYXTXguwPQI6y0Nerz4 3YLDaGdb7idJAybemG/BHNVUG90XnCE5XhKKzcjFfklCly+RzRDhJqfBn7z8eH5e dsK6J0X1Vgeo02tqA4xd3EDK8rdqL2yZfl/2egH8+85R3gDk+kqkfEp4pwCgp6VO aEGVKE6G3fX1R6bSUNJybI0D/jhUEj/HXCs44AF+zIKKSzTCwzfdvjHjjs2uoF7t UJa89W7f0EIhFa10RizIfCsivmPxXPxtCvIYGPrssZdFTSgrmy9jU/9pivueyFWY TM8iKelPanlmwP5tzXJt4LRzU3OpsneUSyu60Tpad1trK/2QeqFRNYFVr7OFnGWB rME5BADOU8Zz+Xc65uKcBtjQXd2razdSuil4fgjHicmIwNYnD2aj6lnc+fnfuAYx NPVxUoWfCS4OaSq09OANwFzyWHRGyS/IetaP1kIaxwkOe1j6r0IiF6ZFpZt1DFYF ikgnJBCYDvG95j/8M6Ta05KERkxbjq2QSW4F4s0ax/Au1tztc4hnBCARCAAnBQJM ikhtIB0BUGxlYXNlIHVzZSAweDA2OUU1NURFIGluc3RlYWQuAAoJEAmKyDpMACjp D3sAnjJSaWwbbbPzYug/Jkg+G4Qy+NlKAJ4geMqNPlyPzCci1vqGpTMZwbPm8rQT cGF6IDxwYXpAbmFkaXIub3JnPohiBBMRAgAiAhsDAh4BAheABQJKAbofBwsJCAcD AgEEFQoIAwUWAgMBAAAKCRAJisg6TAAo6TZkAKCVGY5i5Vty1AHB+Oxw74ek33cP lACgjiUAdpcJ0Nb0xjQQT1JPW79LIe6IYAQTEQIAIQUCSNU7ugIbAwcLCQgHAwIB BBUCCAMEFgIDAQIeAQIXgAAKCRAJisg6TAAo6X7NAJiXMEyWnG743jgn7kapIylO wcAQAJ4742pWNW+u2pyrA2tSTnB5B7g9ILkCDQRI1Tu6EAgA0LZj6Cy3t6vCvbyg 8tNXEBA3fED2nAFnmsMmQhlOhy/yqpa3WFnxZhcqi8v81E9bCQrhh3hGIi/aLdJT 6ENxAvDs2vdNAL3Tz3hB/bTGtSLLbgU64xVuMFD7nNeT17GRmabm8utEnKgf6o/c n4+nS1YPQq64b3CpId7Va67nF58fxBGuNgFy7uNIN6zqblHgPWD/cr2hR5hPX9kk xMgS42PFBqoJZ0I+uaTZRf6pGlsEW9OPIfojK1ttRJKLiykwzxZHRW2qVdl+SiWS HH4TtcxG8HNWShdybimBy4fGM2bIk3P6d/t3gQL5/Q5LEBScoDNOYqqUCXcpdGiA Ji+CEwADBggAjuxoMm6Mc2ST4B0RkiA3PE3rCFhoc4gzjksTNyYuZj9w9JSADa3V l73Su4D4YByCOYxVpdde703dFIlLf4/Gbzdx6ejj5g9Nk3ARR3LtEJsno97HIYQK uM0iyTW1cajAJR7gI+K+YQ07G8vFV81t4DlPD9dHJPV6blgy/HgapnthWJBB5L6b MaAwk+inqbkisyaxE4Ov6mOULqhzyDkGZXlgeaa0wUcyg28WRulPGOG/xICpuM6a FNRKvuBbrX2RH2AiLXwAfclrIe7x7a2RgQcb1tcvfxoQIP7gwAGtsP98dPc1pkma 0GMMcA57HTRKe/T/ZrAVqF3aXdBL48Nc3IhJBBgRAgAJBQJI1Tu6AhsMAAoJEAmK yDpMACjpNwsAnRkZCkPV+RkZmOtoc/UgmZ7AtI3mAJ4vDlEFfTV315Uv73jwVJzi 9PDUAQ== =Latx -----END PGP PUBLIC KEY BLOCK----- schleuder-3.6.0/spec/fixtures/schleuder_at_example_public_key.txt000066400000000000000000000060121401002544500254170ustar00rootroot00000000000000-----BEGIN PGP PUBLIC KEY BLOCK----- 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 /J2/tBYro55u =lep5 -----END PGP PUBLIC KEY BLOCK----- schleuder-3.6.0/spec/fixtures/schleuder_at_example_public_key_minimal.gpg000066400000000000000000000042511401002544500270660ustar00rootroot00000000000000 XF=m֣ҷ$ ?U(mS(CҪMOFx_܍pzvMֺ z{֢`!#-ۖ&kvx9S:¥m\/=wd?{Ogڂ:KћK_b {(s+}CRkg;5ԘlTg57s4lMJxh+ Jkܦ!gCwY,Mxfwk.Pmv!3VnKXZ.;K]y̘9IbIvowb .{i@J2̇%)e&꿏6N ,'Ie#'8{ĵW%,d3ŌymB*wT4t_UtO,,XK1bF^r&>Hߍ,R:lBuele,- zGJ2X h2 nB_!$T#|nQ\htz֫3"B,w*Schleuder TestUser 8"XF=   cPDuC(%_v I¸gٰd6v h+R卞]cnV2ِ7vk&@Xp)+'ƣ2N` 19GmR6NVwl]5HNUZ(Rѐ?[iZE}lZܜfA gS!'Rl)ÐdwAG%fq- goz+GxEȉN)~é[}qXh= qŊŻ1ӱt9V n2]ٖ6Q%ޛl'sqh \d_ kx妆- ?e61ƢTCv36/?[!1qDYq[X_ϱ#"ZXu-!L|ֹ XF=0̖WuŊ|Cj`5T(LV4px \z|fR:ByGE=ls"7DzM֞,@~5dt2i2Y>b|D{zpn"ŒG+;!# I1%$L(z=75sIid*r~K$YWP-$"SFz cҜ]l2 m6N9DT*EOF l dmNJ+j炇nW0b0%.!8!I ,7>MJûr( G.O3\ \$-I͜mՀ h]4O@PyZqWqAkCH)C}_YLtj_̵!El.nlz/0+!$r^VkY }+ ;E/iVA%:@m:`Q;dӾ]Ѩjk}+p d#c: ߗ' a:9'\QOfs$yB32d# y'uOnBug1@rΒ4zxj> B٧?׹C\{2gG^ U ~:?Ⓙ-{ TmQKM")*]|e g.a:+nschleuder-3.6.0/spec/fixtures/schleuder_at_example_public_key_minimal_base64.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-3.6.0/spec/fixtures/signonly_key.txt000066400000000000000000000016651401002544500215570ustar00rootroot00000000000000-----BEGIN PGP PUBLIC KEY BLOCK----- mQENBFmC2g4BCADDRv16LnKRbVT9uyjtNkReqM0abvWUKZOBGYr1JV8t8hEeMKwv BpPwh1AZyw+Ihhn/BybwyBDfqmInKWE81bGUl0ZRTaX2i/5JP7uTIcn/7DY3O4rN Hx/h/Xworqq34MhdoxJCsxFlaEyPaNg9bNNVknoKDRpPTMWBCOhLlvJTr2Lr6gbk bDt62fRR6qrwA7Um28jz2j0Dn0bFKv7mDFlQ4zVL89z93oa5G5JRztogWv4FyawM slSrvLhMt+Jw8HOL2w0vyPuZTcITgy8mcyajF2/NnP6aW5p6ujXIw4od3gJtDUOI Uec+ZMFSDvD1jzv42ksHz5D4SkuWWrtffwfxABEBAAG0H3NpZ25vbmx5IDxzaWdu b25seUBleGFtcGxlLm9yZz6JAU4EEwEKADgWIQSxzYuxXCZzxr/Y+ktwss8p4BrV PgUCWYLaDgIbAwULCQgHAwUVCgkICwUWAgMBAAIeAQIXgAAKCRBwss8p4BrVPgj+ B/9hs+NMmdjOM/3KGrL65qVKwAe/zR0xVhmnT+kg9XkCuH1dKT2vae5zkzvU883R DTwk5nFpKFuklYDyTtpOxZkmNXzYIBihFdqWLdg9SO/ydXwFB5dcsinAadWYTNg6 NS6hA5hG7Uc3zush8DzvUvR9JPdKTXLZ4zKNZLJ/SdLQO+e3lgDkfkJ9RH4VNFja Fys4nXVLOAnj39Yngcz6e1xngvqM4453/XgHtxg9AnDj4w09LgdoVfonPwKiLiZ7 f7eFeaHdQr+OWI/0A4Nghzd1SHnBSvlDS7XRiuiu1SYkDWK6M8c7p+It3wHAUeG3 tXmKTndc5oY20DAh14ez7kt6 =SgbM -----END PGP PUBLIC KEY BLOCK----- schleuder-3.6.0/spec/fixtures/v2list/000077500000000000000000000000001401002544500175175ustar00rootroot00000000000000schleuder-3.6.0/spec/fixtures/v2list/list.conf000066400000000000000000000021241401002544500213400ustar00rootroot00000000000000--- headers_to_meta: - :from - :to - :cc - :date receive_from_member_emailaddresses_only: false keep_msgid: true log_level: WARN log_syslog: false keywords_admin_only: - ADD-MEMBER - DELETE-MEMBER - DELETE-KEY - SAVE-MEMBERS - DEL-KEY myname: v2 List default_mime: MIME receive_authenticated_only: false receive_admin_only: false bounces_drop_all: false include_list_headers: true myaddr: v2list@example.org key_fingerprint: 0392CF72B345256BB730049789226FD6A42B2A7A log_file: list.log archive: false prefix_out: "[out]" log_io: false openpgp_header_preference: signencrypt prefix: "[v2]" bounces_drop_on_headers: x-spam-flag: "yes" receive_encrypted_only: false bounces_notify_admin: true max_message_size: 10240 gpg_password: te=65k:3N4*leKo[js:=[+p[DGFd%6ui send_encrypted_only: false receive_signed_only: false public_footer: "-- \nfooter" dump_incoming_mail: false include_openpgp_header: true admins: - key_fingerprint: C4D60F8833789C7CAA44496FD3FFA6613AB10ECE mime: MIME email: schleuder2@example.org encrypted_only: false prefix_in: "[in]" keywords_admin_notify: - ADD-KEY - UNSUBSCRIBE schleuder-3.6.0/spec/fixtures/v2list/list.log000066400000000000000000000000001401002544500211630ustar00rootroot00000000000000schleuder-3.6.0/spec/fixtures/v2list/members.conf000066400000000000000000000007351401002544500220250ustar00rootroot00000000000000--- - email: anotherone@example.org # 2 matching keys - email: anyone@example.org # pinned fingerprint key_fingerprint: C4D60F8833789C7CAA44496FD3FFA6613AB10ECE mime: MIME encrypted_only: false - email: bla@foo # 2 matching keys, 1 of which is expired - email: old@example.org # has matching key in keyring - email: schleuder2@example.org # also set as admin - email: someone@example.org # no matching key encrypted_only: true schleuder-3.6.0/spec/fixtures/v2list/pubring.gpg000066400000000000000000000277211401002544500216750ustar00rootroot00000000000000 XuDo)?jEFfńpH䆐mmH>RSUMbMG֜,k*'wǣ& ȅ^ncZo+őC?;5Uv*y~>`1luU{H>]XnY]bcA $Ӯn S_vXf :D(+^R 'p{u⽮er o¤15Lev%)5c1fj/[7/`€]j,^,<7SB'>A6dxއu <Ԗ9 pEpvqm!t Bf>q2nYXVg5_-zK'?::v;n;ﻄo>7Hs΅:Ӥ>1-]u`HU-qHV,@w})c sDW|i @vg(!d"'JzJ8/3v2 List (schleuder list) 8"XuD/   "o֤+*zOhudX[07{-y,ry|1R*q$VQtٓO"eQ:Ǐ5?PJ`"Mq$ӳ}fD%Ezaֱ" ZęŤ-'WtWo. ȕ36Nq!X6S[u[Ӥq_yl v8hfpoQ4'<>8GhcĤPՐOP}9NZ&U\>} [m֏V*'RIK2dv&d z~*(rEWPmo-+)d *7utq!o4ׯ0 ' ,8)gb>*2>kLɒctU"wdCnPx1tG֙}@UAT<;NLl5FI-qU"c|b댷VuґkbIV4f-v2 List (schleuder list) ;%/  XuD "o֤+*zLyB`A8(rP5r7ɥ͆\0#ځ mfQ'.WN8P:ԁ<_J%/t`J.胔ؿ)eW)&'CY,JcCts'k \Z!n [d*f09KR}_s"h}FGp%YUJ8'G$8"XuD/   "o֤+*zk8o''%Oih|/d~*Xh˃rW3:Nhnk7#M"|~'2yZx6J~ӵyq$(LqP}6~K?@!}zW%I8 WQ5wWrzdQÅxH%Z&K^3w^rJsudV-S^e?s? gbDr=ғ:"r)qQЬgcS[asK԰]X%'@B8#1[=OZŽN>|~M9[\Nt"Gyr<;)|Iqܥ>BڬeOr!y(ܾ9)C XuD ]LD-zN LR,B t(_ w[ǂP&!P^}7O6` 0gTM8لRB *P4I8W;~ Y'J_o.Kf ଇZL 3az'o-`{%q)qY-08Ä'H˪gX,kJX|ɒWI)D/kJ m+{d^|H-H!( Ϋa1~,D?҂(4*-j?*doyif)ݵPʞ7AwS=VKtr,*7bKqer 9?>^7y-ࠝaKZ O#o6kqL^~-chwhA)`S&7tܕ΅"֔&+`l/[k·VZ>Ts/G` QlTڀay^l2N>E(^gHĤ5#P-dKzP`i6P\> XuD.) "o֤+*z] XuD ŷ'B!o1g^"۝rV4)%l n24%#RKJcմ}o} :<nN)!X{1߽5LGXg(R3'7MV4Lmd+Kݱm^W/JM~cy%Beѷ\䇞rB֧p> 8ܯ+Yv8Llaj]Խ_ h'gS/$[g%5݇UEȵiF4*i Ubrp2Y ~a-S aw"H Dq}( *XF n ;QjCeOLj4$rL ى5R?UB }G9KF1wH|r)1D#tv?{alzBaza6?گ_eʓbc)q;_okFStTt"gAp*0maXucvjm}3P|4ͫm)Another Testuser 8"XN   a:zd 9~l^|55/J';,s V~YAɧ^zh{C %~okIY\?Xtngb#]J%D+#^<D,Nف LnBGMr2;q {vJk؅un澹` kIWu1Iޫx|Ve8Jܪ2PY[bzޑG)>x+ʹg!foFX` "VIݝNXE~b~>"%r1adZTr1]d"(RQϟ&x~<,;#EMnhP\7QAJ҂V̵TS=-id?2'v z+}~QM"*;Du"wa_p&՟eε,!nReЋ|=VVMlȻl^+GfC`gԺP4bxB޾N~ a5w{ ]G-r XC{ 9 bY)b/@h-s#.8.sFeq 6R BPf8?)3:޲|: x,;zM1+bZRU] GKG6U@.ZWǑ=p\ XN a:-z_3&Q)>b%eYJœIn`}wVXLܳ5puIVHZL,EYc6WNgyCRQ;q<`*ٓ$<3exn&LB/t3'ԉmbt5+jTZ[o3\* BeGy].4,}R㸂!_s&@ .@~T|DQevRy>"~1ʫ'LYׂ;۫Y dkOUzhdp|Lf&cH͍xIY_/wݔHf-V26CP2И\ "_K} MaJL*`BC?glԈOP1\sC&mwuD1\_k`8|ЏJv%+yK@!'&YנK{52G 1̛h@wWj)5nu~ Xyzt8u7S:bi'Ϩʁ5n263LbKj< UKFv'G-!6b@ LH X [.9潴ĉJKc^ǗD%]@4XK::&2JQÏbGac]=Jk iM[):;P$ñJ*_-o87ty-b/B,pvzBܧold uid N 8   !nx 3e! fXy ! f>CZt|%;`vJ 50/8UK0ԁG8Z7G0 j=G:0lt+ڰصy f}ϙZ\\*Miy i߃tG2HAO{cwEpW Z*Vbw%oq(RaěP@{[Șzbq?ŋz;d]O$.iAGb%Az4.TZz)3#B1 Xy5>fY$)Ku0R!'WWKc@I閿wf:"FA6Zٽg] a*-x6B&2׌G# Ϻ|"@< x[OXOՋu(%LiAYu꺏i gBu z"un[],ၜuh+^l]!]H҃(cp(hgݵ|==^P#6  !nx 3e! fXy ! fMIza(AtY *+l6wnrAMx;8)np p#fzB οt_C\o zRljKZmo4+7(X= c j[.yV*U#y]"7-ʈOgUg DjȮ;X͢ ~sq/YybI lD y ]Rvuh/AUčҭƝMLz#`:@+$^3R Y=?c$c<.0`=Cv0D欚OJ2Sny>s䘚P ^Yŗø']B(Z`_zds 6 %MKn$UetH>pJ~u2a!$~`)Z]yˣ8*4t*<$s͖hB08yxLjUFC?H794AxH!ERW8"Y=?   DYKQM=sMR%j+nĔB^Y#OzNe-7U,J"<9 z l Dgr6(^cZ,S{A볡++E7^ϑ-S{t~&(lW){ߎ㚤ZrM5c vu*GR~<v.ݦg~-#RqSQO=m봺Ŭ^e aJG)fxζ}{zU_'&JD5M~~|ƞ2c䍧 ^Y}~Wk97`DS3‚ Y=p,Iv_w!')0 =7-rΛx+*iKp-;7C8"Y=    y'MUĞcr+_d!m@-rpC: lΊV v_O$FSrjf5G];,p"2xwP/ߍ.$ bHU)hs}4ULcʯ/ a0_V07͖5,>W ,__;F`%^q!Sf UUvۊ7N"Osk>يL8r,S3,ʕ-?)W Y=oB=G 4 Q&/`+=̥WPؙv?_7_7GiQ@x1 =#oX sR*mKV:ʪ8@)vbJDO.跑o`abTu4Ex>t!j_7c@_깷+0pyڭUb,9딳K- Y=  y'M+y0٘zGH{(u{`ʆʜUs%/+I'/EWo,b+'$bfc<uzbfPN~z>g8{*CK=˛ž|RZvAP4&UN5LP\r2n(m/ %I"MKJs+kXr J d'> 5V LeY2rW@ Md 7Cpr(sf:J×_8VO߹PuȯT)!KTnb[PA!B0z8jzXJ46#DCU78 Ll~&*eFΚo R0maėN31&U j"#h,k=?PQ# Hz:ɱu4K@r,rpcPW Iexpired >(LeY Q   ?8^. ѣIn,oN]N,Y#섣m9[A !y(7LBV×=~7vIM񤿎ݔ[dcܛ2 D һUҌ5Dk >rOGJ]" ^T8#t/= MSꁩB傓M8}"x㞪4,z/ 57Ë4x;v?B*&46TȂoJܲmi1 LeYLK9:[P.hS*1iOLo{2\UcxVd17nvI ɐNc%c~4TąXo$zhHr AmԔ5VQLY'Ga oY=O}lP84{Xq\Wu ]<3s><[, w0 NdZCE>NMd l\wC%LeY  Q ?8A tKe'ӌyjMА*5$#W )EZQSgI䙘 4 8@F¬Zh ѽ|<#r)u{JW!IU`,lbHngEQYnڟrj>jLqAp#H*nKr/fLUd{~ "4D3/Ued6Ȅ=%z[Vl+-w6GkID%v3:0xFvDPᙰ K nA+Ȧ-DZ?)$ u)9\X}d&TT7TIYGkxgbƖ+E)HNtΉ>ٙRr=ʴۑX5$ӛEމ!*%o(^7.bW X3_blabla 8"K   %$T&WpzR;տbJGV|ܷfMW.vE%߱C'2q0LB^a5_Qō:y ѓlpk[*r;g&CJ :8E**$\{7m0v ZuAmB 53-Ӎ3ʽo!{xPrvm+~Wa0u)jByB|v^Ҥngl~ KtP]AȦ~=؜@zLG=tju4GO7[iHyR&E$52&LXu1Xt &$g;Zt-wS_ ΔH?x+kY9@DHYF]eA?(5 "hiy_^>j5Sy4$K79 #tw |:kY=e^x#M K %$,1جL6LX(ֶG ~v5R Ư ,L‹M,k l()(QW[U#GXƟ ~+qbrMFk,@)hˤ"ZlŃOW3~&;"pt8>c4,M`՛w|ܢB e.ub$C|c;gRjeiv>2p=?Z~%L5s430TJkq@<schleuder-3.6.0/spec/fixtures/v2list/random_seed000066400000000000000000000011301401002544500217150ustar00rootroot00000000000000Dw3!"\޴t^2e8+\l`~ucԇc{mPχQ#a[ qYز[,KR %M )94n2LdT  fdE}H1c:ߗ2T=ʙL6"k"h/!&JS8)=EH-&D]f TTf+Lc j`Y$Q/H/O/xz7q]8{ltST{ۢdy15`O斢/g-N,GdF'pYa!\feX,RM>K]ehH;r#$(S OHschleuder-3.6.0/spec/fixtures/v2list/secring.gpg000066400000000000000000000150361401002544500216550ustar00rootroot00000000000000=XuDo)?jEFfńpH䆐mmH>RSUMbMG֜,k*'wǣ& ȅ^ncZo+őC?;5Uv*y~>`1luU{H>]XnY]bcA $Ӯn S_vXf :D(+^R 'p{u⽮er o¤15Lev%)5c1fj/[7/`€]j,^,<7SB'>A6dxއu <Ԗ9 pEpvqm!t Bf>q2nYXVg5_-zK'?::v;n;ﻄo>7Hs΅:Ӥ>1-]u`HU-qHV,@w})c sDW|i @vg(!d"'JzJ8/.y:ʦ)`?^Jx n|S2;oQ'j}|Xrp~&1OwARI\5P D'-Ag9;wK9rVvlwi }UI# Fq- SSך-Rԉl*#+n2HoXBR ®" 2]ZBLJL#+ᰝo n,?eTʩEz2oO_5ioǽ=ԋ~4qFfכ> ^[ˉ&( )nTa9ק~9n>rRѳ:ͽчPXvȿάY'aAFTFuv"㸇, z,E1px]dG@c DTJ_[bY;k "{i3[z ifʌ6σF|-ڲkķ&^&c~PNyW|I;B*x첵Z7,,0!SMύEbNfKsrw[WVn]Z|o%3)Ub`Sgela§CgOi7hZƬH3t}H<5pԈYd\Hukް;bR}>[˖Yb*PfA#.RVD# 8] v?BIRSwqΧ02݁pt<K^V̶ Dj6KW0$CI޹S5L|z N.kEJlzF¶#аU@H&L[fk; u[MaAO/qchfn-rΪҘչ&KoGE ڕ{64`pn/U@wn2&xb2}pߌ5vky/$ ۛaqnL'v^x#Sܑ~qUt/.ɩ͇GH.+o[f g荝KGxNA~&v{:"B&z8"XuD/   "o֤+*zBb7L^ 9iH,@. Ae>.*d%Cv VnOc::|{'[[ڢz\ lH'0jF̘m15{QaX 1Ҭ/Xs;9;w1l"dXPªQ ;/@e&)S{KTТYl'NGC+\y+bsOD@?&<2}d_ᛥݓ/|ktB1 9n5g DFC@TgD3<;MYV.>XXoeА9c#Z1r>Mu_Iid%s$ϛN`~T89 LL?%M;0];`ڐ/pOQ6t r8p`(eP^Td9XCJfFm:5v2 List (schleuder list) 8"XuD/   "o֤+*zk8o''%Oih|/d~*Xh˃rW3:Nhnk7#M"|~'2yZx6J~ӵyq$(LqP}6~K?@!}zW%I8 WQ5wWrzdQÅxH%Z&K^3w^rJsudV-S^e?s? gbDr=ғ:"r)qQЬgcS[asK԰]X%'@B8#1[=OZŽN>|~M9[\Nt"Gyr<;)|Iqܥ>BڬeOr!y(ܾ9)C3v2 List (schleuder list) 8"XuD/   "o֤+*zOhudX[07{-y,ry|1R*q$VQtٓO"eQ:Ǐ5?PJ`"Mq$ӳ}fD%Ezaֱ" ZęŤ-'WtWo. ȕ36Nq!X6S[u[Ӥq_yl v8hfpoQ4'<>8GhcĤPՐOP}9NZ&U\>} [m֏V*'RIK2dv&d z~*(rEWPmo-+)d *7utq!o4ׯ0 ' ,8)gb>*2>kLɒctU"wdCnPx1tG֙}@UAT<;NLl5FI-qU"c|b댷VuґkbIV4f>XuD ]LD-zN LR,B t(_ w[ǂP&!P^}7O6` 0gTM8لRB *P4I8W;~ Y'J_o.Kf ଇZL 3az'o-`{%q)qY-08Ä'H˪gX,kJX|ɒWI)D/kJ m+{d^|H-H!( Ϋa1~,D?҂(4*-j?*doyif)ݵPʞ7AwS=VKtr,*7bKqer 9?>^7y-ࠝaKZ O#o6kqL^~-chwhA)`S&7tܕ΅"֔&+`l/[k·VZ>Ts/G` QlTڀay^l2N>E(^gHĤ5#P-dKzP`i6P\.y:ʦ)`tlv90GGQFax_5p!XE,>XI**.ַ%oB0”{PmP wCBߡ%hVa1 rC`@۳U#)a.\ܦii>`C$vT:*l m/9KWپ,*#]ҍ%"p`ՏgS*fǯ"x{Ը}:5C80D`0$  mPD7 cel-(!L?eb[Ơ/'!L2ϵށ1w6cۓ_ nD$ 3v+&(TY&iu t砥)ȓw=Iaʷ$8Ѳ38ȇDGT{~:O^rWnNUAa[9${ '~w?ـkT oa`\9V tmS>}um4-J a>콉!L %sL7Z%ߚ>W;oݽq@` e3xa'w8tѰ)GO`SfSaUb%pT9kwU'b џd~bSpe|}vg6oRQ] ܙ;{B鯨܉8d`x-.8%C>7*z*gj(}fKcU LN&O-VH׫KOXt˥V,6M1|;d^P"cR_/Ŗrqae)?sMb$g'4̇!4  4A '.! 㯙g`0CT0:s,aܥ¸(#a` O|0 1xW h,/ b ԝ,Nw nx(o>_۰%:)h]&PDBUtt]aF> XuD.) "o֤+*z] XuD ŷ'B!o1g^"۝rV4)%l n24%#RKJcմ}o} :<nN)!X{1߽5LGXg(R3'7MV4Lmd+Kݱm^W/JM~cy%Beѷ\䇞rB֧p> 8ܯ+Yv8Llaj]Խ_ h'gS/$[g%5݇UEȵiF4*i Ubrp2YRSUMbMG֜,k*'wǣ& ȅ^ncZo+őC?;5Uv*y~>`1luU{H>]XnY]bcA $Ӯn S_vXf :D(+^R 'p{u⽮er o¤15Lev%)5c1fj/[7/`€]j,^,<7SB'>A6dxއu <Ԗ9 pEpvqm!t Bf>q2nYXVg5_-zK'?::v;n;ﻄo>7Hs΅:Ӥ>1-]u`HU-qHV,@w})c sDW|i @vg(!d"'JzJ8/3v2 List (schleuder list) 8"XuD/   "o֤+*zOhudX[07{-y,ry|1R*q$VQtٓO"eQ:Ǐ5?PJ`"Mq$ӳ}fD%Ezaֱ" ZęŤ-'WtWo. ȕ36Nq!X6S[u[Ӥq_yl v8hfpoQ4'<>8GhcĤPՐOP}9NZ&U\>} [m֏V*'RIK2dv&d z~*(rEWPmo-+)d *7utq!o4ׯ0 ' ,8)gb>*2>kLɒctU"wdCnPx1tG֙}@UAT<;NLl5FI-qU"c|b댷VuґkbIV4f-v2 List (schleuder list) ;%/  XuD "o֤+*zLyB`A8(rP5r7ɥ͆\0#ځ mfQ'.WN8P:ԁ<_J%/t`J.胔ؿ)eW)&'CY,JcCts'k \Z!n [d*f09KR}_s"h}FGp%YUJ8'G$8"XuD/   "o֤+*zk8o''%Oih|/d~*Xh˃rW3:Nhnk7#M"|~'2yZx6J~ӵyq$(LqP}6~K?@!}zW%I8 WQ5wWrzdQÅxH%Z&K^3w^rJsudV-S^e?s? gbDr=ғ:"r)qQЬgcS[asK԰]X%'@B8#1[=OZŽN>|~M9[\Nt"Gyr<;)|Iqܥ>BڬeOr!y(ܾ9)C XuD ]LD-zN LR,B t(_ w[ǂP&!P^}7O6` 0gTM8لRB *P4I8W;~ Y'J_o.Kf ଇZL 3az'o-`{%q)qY-08Ä'H˪gX,kJX|ɒWI)D/kJ m+{d^|H-H!( Ϋa1~,D?҂(4*-j?*doyif)ݵPʞ7AwS=VKtr,*7bKqer 9?>^7y-ࠝaKZ O#o6kqL^~-chwhA)`S&7tܕ΅"֔&+`l/[k·VZ>Ts/G` QlTڀay^l2N>E(^gHĤ5#P-dKzP`i6P\> XuD.) "o֤+*z] XuD ŷ'B!o1g^"۝rV4)%l n24%#RKJcմ}o} :<nN)!X{1߽5LGXg(R3'7MV4Lmd+Kݱm^W/JM~cy%Beѷ\䇞rB֧p> 8ܯ+Yv8Llaj]Խ_ h'gS/$[g%5݇UEȵiF4*i Ubrp2Y ~a-S aw"H Dq}( *XF n ;QjCeOLj4$rL ى5R?UB }G9KF1wH|r)1D#tv?{alzBaza6?گ_eʓbc)q;_okFStTt"gAp*0maXucvjm}3P|4ͫm)Another Testuser 8"XN   a:zd 9~l^|55/J';,s V~YAɧ^zh{C %~okIY\?Xtngb#]J%D+#^<D,Nف LnBGMr2;q {vJk؅un澹` kIWu1Iޫx|Ve8Jܪ2PY[bzޑG)>x+ʹg!foFX` "VIݝNXE~b~>"%r1adZTr1]d"(RQϟ&x~<,;#EMnhP\7QAJ҂V̵TS=-id?2'v z+}~QM"*;Du"wa_p&՟eε,!nReЋ|=VVMlȻl^+GfC`gԺP4bxB޾N~ a5w{ ]G-r XC{ 9 bY)b/@h-s#.8.sFeq 6R BPf8?)3:޲|: x,;zM1+bZRU] GKG6U@.ZWǑ=p\ XN a:-z_3&Q)>b%eYJœIn`}wVXLܳ5puIVHZL,EYc6WNgyCRQ;q<`*ٓ$<3exn&LB/t3'ԉmbt5+jTZ[o3\* BeGy].4,}R㸂!_s&@ .@~T|DQevRy>"~1ʫ'LYׂ;۫Y dkOUzhdp|Lf&cH͍xIY_/wݔHf-V26CP2И\ "_K} MaJL*`BC?glԈOP1\sC&mwuD1\_k`8|ЏJv%+yK@!'&YנK{52G 1̛h@wWj)5nu~schleuder-3.6.0/spec/fixtures/v2list_admin_non_delivery/random_seed000066400000000000000000000011301401002544500256420ustar00rootroot00000000000000Dw3!"\޴t^2e8+\l`~ucԇc{mPχQ#a[ qYز[,KR %M )94n2LdT  fdE}H1c:ߗ2T=ʙL6"k"h/!&JS8)=EH-&D]f TTf+Lc j`Y$Q/H/O/xz7q]8{ltST{ۢdy15`O斢/g-N,GdF'pYa!\feX,RM>K]ehH;r#$(S OHschleuder-3.6.0/spec/fixtures/v2list_admin_non_delivery/secring.gpg000066400000000000000000000150361401002544500256020ustar00rootroot00000000000000=XuDo)?jEFfńpH䆐mmH>RSUMbMG֜,k*'wǣ& ȅ^ncZo+őC?;5Uv*y~>`1luU{H>]XnY]bcA $Ӯn S_vXf :D(+^R 'p{u⽮er o¤15Lev%)5c1fj/[7/`€]j,^,<7SB'>A6dxއu <Ԗ9 pEpvqm!t Bf>q2nYXVg5_-zK'?::v;n;ﻄo>7Hs΅:Ӥ>1-]u`HU-qHV,@w})c sDW|i @vg(!d"'JzJ8/.y:ʦ)`?^Jx n|S2;oQ'j}|Xrp~&1OwARI\5P D'-Ag9;wK9rVvlwi }UI# Fq- SSך-Rԉl*#+n2HoXBR ®" 2]ZBLJL#+ᰝo n,?eTʩEz2oO_5ioǽ=ԋ~4qFfכ> ^[ˉ&( )nTa9ק~9n>rRѳ:ͽчPXvȿάY'aAFTFuv"㸇, z,E1px]dG@c DTJ_[bY;k "{i3[z ifʌ6σF|-ڲkķ&^&c~PNyW|I;B*x첵Z7,,0!SMύEbNfKsrw[WVn]Z|o%3)Ub`Sgela§CgOi7hZƬH3t}H<5pԈYd\Hukް;bR}>[˖Yb*PfA#.RVD# 8] v?BIRSwqΧ02݁pt<K^V̶ Dj6KW0$CI޹S5L|z N.kEJlzF¶#аU@H&L[fk; u[MaAO/qchfn-rΪҘչ&KoGE ڕ{64`pn/U@wn2&xb2}pߌ5vky/$ ۛaqnL'v^x#Sܑ~qUt/.ɩ͇GH.+o[f g荝KGxNA~&v{:"B&z8"XuD/   "o֤+*zBb7L^ 9iH,@. Ae>.*d%Cv VnOc::|{'[[ڢz\ lH'0jF̘m15{QaX 1Ҭ/Xs;9;w1l"dXPªQ ;/@e&)S{KTТYl'NGC+\y+bsOD@?&<2}d_ᛥݓ/|ktB1 9n5g DFC@TgD3<;MYV.>XXoeА9c#Z1r>Mu_Iid%s$ϛN`~T89 LL?%M;0];`ڐ/pOQ6t r8p`(eP^Td9XCJfFm:5v2 List (schleuder list) 8"XuD/   "o֤+*zk8o''%Oih|/d~*Xh˃rW3:Nhnk7#M"|~'2yZx6J~ӵyq$(LqP}6~K?@!}zW%I8 WQ5wWrzdQÅxH%Z&K^3w^rJsudV-S^e?s? gbDr=ғ:"r)qQЬgcS[asK԰]X%'@B8#1[=OZŽN>|~M9[\Nt"Gyr<;)|Iqܥ>BڬeOr!y(ܾ9)C3v2 List (schleuder list) 8"XuD/   "o֤+*zOhudX[07{-y,ry|1R*q$VQtٓO"eQ:Ǐ5?PJ`"Mq$ӳ}fD%Ezaֱ" ZęŤ-'WtWo. ȕ36Nq!X6S[u[Ӥq_yl v8hfpoQ4'<>8GhcĤPՐOP}9NZ&U\>} [m֏V*'RIK2dv&d z~*(rEWPmo-+)d *7utq!o4ׯ0 ' ,8)gb>*2>kLɒctU"wdCnPx1tG֙}@UAT<;NLl5FI-qU"c|b댷VuґkbIV4f>XuD ]LD-zN LR,B t(_ w[ǂP&!P^}7O6` 0gTM8لRB *P4I8W;~ Y'J_o.Kf ଇZL 3az'o-`{%q)qY-08Ä'H˪gX,kJX|ɒWI)D/kJ m+{d^|H-H!( Ϋa1~,D?҂(4*-j?*doyif)ݵPʞ7AwS=VKtr,*7bKqer 9?>^7y-ࠝaKZ O#o6kqL^~-chwhA)`S&7tܕ΅"֔&+`l/[k·VZ>Ts/G` QlTڀay^l2N>E(^gHĤ5#P-dKzP`i6P\.y:ʦ)`tlv90GGQFax_5p!XE,>XI**.ַ%oB0”{PmP wCBߡ%hVa1 rC`@۳U#)a.\ܦii>`C$vT:*l m/9KWپ,*#]ҍ%"p`ՏgS*fǯ"x{Ը}:5C80D`0$  mPD7 cel-(!L?eb[Ơ/'!L2ϵށ1w6cۓ_ nD$ 3v+&(TY&iu t砥)ȓw=Iaʷ$8Ѳ38ȇDGT{~:O^rWnNUAa[9${ '~w?ـkT oa`\9V tmS>}um4-J a>콉!L %sL7Z%ߚ>W;oݽq@` e3xa'w8tѰ)GO`SfSaUb%pT9kwU'b џd~bSpe|}vg6oRQ] ܙ;{B鯨܉8d`x-.8%C>7*z*gj(}fKcU LN&O-VH׫KOXt˥V,6M1|;d^P"cR_/Ŗrqae)?sMb$g'4̇!4  4A '.! 㯙g`0CT0:s,aܥ¸(#a` O|0 1xW h,/ b ԝ,Nw nx(o>_۰%:)h]&PDBUtt]aF> XuD.) "o֤+*z] XuD ŷ'B!o1g^"۝rV4)%l n24%#RKJcմ}o} :<nN)!X{1߽5LGXg(R3'7MV4Lmd+Kݱm^W/JM~cy%Beѷ\䇞rB֧p> 8ܯ+Yv8Llaj]Խ_ h'gS/$[g%5݇UEȵiF4*i Ubrp2YRSUMbMG֜,k*'wǣ& ȅ^ncZo+őC?;5Uv*y~>`1luU{H>]XnY]bcA $Ӯn S_vXf :D(+^R 'p{u⽮er o¤15Lev%)5c1fj/[7/`€]j,^,<7SB'>A6dxއu <Ԗ9 pEpvqm!t Bf>q2nYXVg5_-zK'?::v;n;ﻄo>7Hs΅:Ӥ>1-]u`HU-qHV,@w})c sDW|i @vg(!d"'JzJ8/3v2 List (schleuder list) 8"XuD/   "o֤+*zOhudX[07{-y,ry|1R*q$VQtٓO"eQ:Ǐ5?PJ`"Mq$ӳ}fD%Ezaֱ" ZęŤ-'WtWo. ȕ36Nq!X6S[u[Ӥq_yl v8hfpoQ4'<>8GhcĤPՐOP}9NZ&U\>} [m֏V*'RIK2dv&d z~*(rEWPmo-+)d *7utq!o4ׯ0 ' ,8)gb>*2>kLɒctU"wdCnPx1tG֙}@UAT<;NLl5FI-qU"c|b댷VuґkbIV4f-v2 List (schleuder list) ;%/  XuD "o֤+*zLyB`A8(rP5r7ɥ͆\0#ځ mfQ'.WN8P:ԁ<_J%/t`J.胔ؿ)eW)&'CY,JcCts'k \Z!n [d*f09KR}_s"h}FGp%YUJ8'G$8"XuD/   "o֤+*zk8o''%Oih|/d~*Xh˃rW3:Nhnk7#M"|~'2yZx6J~ӵyq$(LqP}6~K?@!}zW%I8 WQ5wWrzdQÅxH%Z&K^3w^rJsudV-S^e?s? gbDr=ғ:"r)qQЬgcS[asK԰]X%'@B8#1[=OZŽN>|~M9[\Nt"Gyr<;)|Iqܥ>BڬeOr!y(ܾ9)C XuD ]LD-zN LR,B t(_ w[ǂP&!P^}7O6` 0gTM8لRB *P4I8W;~ Y'J_o.Kf ଇZL 3az'o-`{%q)qY-08Ä'H˪gX,kJX|ɒWI)D/kJ m+{d^|H-H!( Ϋa1~,D?҂(4*-j?*doyif)ݵPʞ7AwS=VKtr,*7bKqer 9?>^7y-ࠝaKZ O#o6kqL^~-chwhA)`S&7tܕ΅"֔&+`l/[k·VZ>Ts/G` QlTڀay^l2N>E(^gHĤ5#P-dKzP`i6P\> XuD.) "o֤+*z] XuD ŷ'B!o1g^"۝rV4)%l n24%#RKJcմ}o} :<nN)!X{1߽5LGXg(R3'7MV4Lmd+Kݱm^W/JM~cy%Beѷ\䇞rB֧p> 8ܯ+Yv8Llaj]Խ_ h'gS/$[g%5݇UEȵiF4*i Ubrp2Y ~a-S aw"H Dq}( *XF n ;QjCeOLj4$rL ى5R?UB }G9KF1wH|r)1D#tv?{alzBaza6?گ_eʓbc)q;_okFStTt"gAp*0maXucvjm}3P|4ͫm)Another Testuser 8"XN   a:zd 9~l^|55/J';,s V~YAɧ^zh{C %~okIY\?Xtngb#]J%D+#^<D,Nف LnBGMr2;q {vJk؅un澹` kIWu1Iޫx|Ve8Jܪ2PY[bzޑG)>x+ʹg!foFX` "VIݝNXE~b~>"%r1adZTr1]d"(RQϟ&x~<,;#EMnhP\7QAJ҂V̵TS=-id?2'v z+}~QM"*;Du"wa_p&՟eε,!nReЋ|=VVMlȻl^+GfC`gԺP4bxB޾N~ a5w{ ]G-r XC{ 9 bY)b/@h-s#.8.sFeq 6R BPf8?)3:޲|: x,;zM1+bZRU] GKG6U@.ZWǑ=p\ XN a:-z_3&Q)>b%eYJœIn`}wVXLܳ5puIVHZL,EYc6WNgyCRQ;q<`*ٓ$<3exn&LB/t3'ԉmbt5+jTZ[o3\* BeGy].4,}R㸂!_s&@ .@~T|DQevRy>"~1ʫ'LYׂ;۫Y dkOUzhdp|Lf&cH͍xIY_/wݔHf-V26CP2И\ "_K} MaJL*`BC?glԈOP1\sC&mwuD1\_k`8|ЏJv%+yK@!'&YנK{52G 1̛h@wWj)5nu~schleuder-3.6.0/spec/fixtures/v2list_admin_without_key/random_seed000066400000000000000000000011301401002544500255200ustar00rootroot00000000000000Dw3!"\޴t^2e8+\l`~ucԇc{mPχQ#a[ qYز[,KR %M )94n2LdT  fdE}H1c:ߗ2T=ʙL6"k"h/!&JS8)=EH-&D]f TTf+Lc j`Y$Q/H/O/xz7q]8{ltST{ۢdy15`O斢/g-N,GdF'pYa!\feX,RM>K]ehH;r#$(S OHschleuder-3.6.0/spec/fixtures/v2list_admin_without_key/secring.gpg000066400000000000000000000150361401002544500254600ustar00rootroot00000000000000=XuDo)?jEFfńpH䆐mmH>RSUMbMG֜,k*'wǣ& ȅ^ncZo+őC?;5Uv*y~>`1luU{H>]XnY]bcA $Ӯn S_vXf :D(+^R 'p{u⽮er o¤15Lev%)5c1fj/[7/`€]j,^,<7SB'>A6dxއu <Ԗ9 pEpvqm!t Bf>q2nYXVg5_-zK'?::v;n;ﻄo>7Hs΅:Ӥ>1-]u`HU-qHV,@w})c sDW|i @vg(!d"'JzJ8/.y:ʦ)`?^Jx n|S2;oQ'j}|Xrp~&1OwARI\5P D'-Ag9;wK9rVvlwi }UI# Fq- SSך-Rԉl*#+n2HoXBR ®" 2]ZBLJL#+ᰝo n,?eTʩEz2oO_5ioǽ=ԋ~4qFfכ> ^[ˉ&( )nTa9ק~9n>rRѳ:ͽчPXvȿάY'aAFTFuv"㸇, z,E1px]dG@c DTJ_[bY;k "{i3[z ifʌ6σF|-ڲkķ&^&c~PNyW|I;B*x첵Z7,,0!SMύEbNfKsrw[WVn]Z|o%3)Ub`Sgela§CgOi7hZƬH3t}H<5pԈYd\Hukް;bR}>[˖Yb*PfA#.RVD# 8] v?BIRSwqΧ02݁pt<K^V̶ Dj6KW0$CI޹S5L|z N.kEJlzF¶#аU@H&L[fk; u[MaAO/qchfn-rΪҘչ&KoGE ڕ{64`pn/U@wn2&xb2}pߌ5vky/$ ۛaqnL'v^x#Sܑ~qUt/.ɩ͇GH.+o[f g荝KGxNA~&v{:"B&z8"XuD/   "o֤+*zBb7L^ 9iH,@. Ae>.*d%Cv VnOc::|{'[[ڢz\ lH'0jF̘m15{QaX 1Ҭ/Xs;9;w1l"dXPªQ ;/@e&)S{KTТYl'NGC+\y+bsOD@?&<2}d_ᛥݓ/|ktB1 9n5g DFC@TgD3<;MYV.>XXoeА9c#Z1r>Mu_Iid%s$ϛN`~T89 LL?%M;0];`ڐ/pOQ6t r8p`(eP^Td9XCJfFm:5v2 List (schleuder list) 8"XuD/   "o֤+*zk8o''%Oih|/d~*Xh˃rW3:Nhnk7#M"|~'2yZx6J~ӵyq$(LqP}6~K?@!}zW%I8 WQ5wWrzdQÅxH%Z&K^3w^rJsudV-S^e?s? gbDr=ғ:"r)qQЬgcS[asK԰]X%'@B8#1[=OZŽN>|~M9[\Nt"Gyr<;)|Iqܥ>BڬeOr!y(ܾ9)C3v2 List (schleuder list) 8"XuD/   "o֤+*zOhudX[07{-y,ry|1R*q$VQtٓO"eQ:Ǐ5?PJ`"Mq$ӳ}fD%Ezaֱ" ZęŤ-'WtWo. ȕ36Nq!X6S[u[Ӥq_yl v8hfpoQ4'<>8GhcĤPՐOP}9NZ&U\>} [m֏V*'RIK2dv&d z~*(rEWPmo-+)d *7utq!o4ׯ0 ' ,8)gb>*2>kLɒctU"wdCnPx1tG֙}@UAT<;NLl5FI-qU"c|b댷VuґkbIV4f>XuD ]LD-zN LR,B t(_ w[ǂP&!P^}7O6` 0gTM8لRB *P4I8W;~ Y'J_o.Kf ଇZL 3az'o-`{%q)qY-08Ä'H˪gX,kJX|ɒWI)D/kJ m+{d^|H-H!( Ϋa1~,D?҂(4*-j?*doyif)ݵPʞ7AwS=VKtr,*7bKqer 9?>^7y-ࠝaKZ O#o6kqL^~-chwhA)`S&7tܕ΅"֔&+`l/[k·VZ>Ts/G` QlTڀay^l2N>E(^gHĤ5#P-dKzP`i6P\.y:ʦ)`tlv90GGQFax_5p!XE,>XI**.ַ%oB0”{PmP wCBߡ%hVa1 rC`@۳U#)a.\ܦii>`C$vT:*l m/9KWپ,*#]ҍ%"p`ՏgS*fǯ"x{Ը}:5C80D`0$  mPD7 cel-(!L?eb[Ơ/'!L2ϵށ1w6cۓ_ nD$ 3v+&(TY&iu t砥)ȓw=Iaʷ$8Ѳ38ȇDGT{~:O^rWnNUAa[9${ '~w?ـkT oa`\9V tmS>}um4-J a>콉!L %sL7Z%ߚ>W;oݽq@` e3xa'w8tѰ)GO`SfSaUb%pT9kwU'b џd~bSpe|}vg6oRQ] ܙ;{B鯨܉8d`x-.8%C>7*z*gj(}fKcU LN&O-VH׫KOXt˥V,6M1|;d^P"cR_/Ŗrqae)?sMb$g'4̇!4  4A '.! 㯙g`0CT0:s,aܥ¸(#a` O|0 1xW h,/ b ԝ,Nw nx(o>_۰%:)h]&PDBUtt]aF> XuD.) "o֤+*z] XuD ŷ'B!o1g^"۝rV4)%l n24%#RKJcմ}o} :<nN)!X{1߽5LGXg(R3'7MV4Lmd+Kݱm^W/JM~cy%Beѷ\䇞rB֧p> 8ܯ+Yv8Llaj]Խ_ h'gS/$[g%5݇UEȵiF4*i Ubrp2YRSUMbMG֜,k*'wǣ& ȅ^ncZo+őC?;5Uv*y~>`1luU{H>]XnY]bcA $Ӯn S_vXf :D(+^R 'p{u⽮er o¤15Lev%)5c1fj/[7/`€]j,^,<7SB'>A6dxއu <Ԗ9 pEpvqm!t Bf>q2nYXVg5_-zK'?::v;n;ﻄo>7Hs΅:Ӥ>1-]u`HU-qHV,@w})c sDW|i @vg(!d"'JzJ8/3v2 List (schleuder list) 8"XuD/   "o֤+*zOhudX[07{-y,ry|1R*q$VQtٓO"eQ:Ǐ5?PJ`"Mq$ӳ}fD%Ezaֱ" ZęŤ-'WtWo. ȕ36Nq!X6S[u[Ӥq_yl v8hfpoQ4'<>8GhcĤPՐOP}9NZ&U\>} [m֏V*'RIK2dv&d z~*(rEWPmo-+)d *7utq!o4ׯ0 ' ,8)gb>*2>kLɒctU"wdCnPx1tG֙}@UAT<;NLl5FI-qU"c|b댷VuґkbIV4f-v2 List (schleuder list) ;%/  XuD "o֤+*zLyB`A8(rP5r7ɥ͆\0#ځ mfQ'.WN8P:ԁ<_J%/t`J.胔ؿ)eW)&'CY,JcCts'k \Z!n [d*f09KR}_s"h}FGp%YUJ8'G$8"XuD/   "o֤+*zk8o''%Oih|/d~*Xh˃rW3:Nhnk7#M"|~'2yZx6J~ӵyq$(LqP}6~K?@!}zW%I8 WQ5wWrzdQÅxH%Z&K^3w^rJsudV-S^e?s? gbDr=ғ:"r)qQЬgcS[asK԰]X%'@B8#1[=OZŽN>|~M9[\Nt"Gyr<;)|Iqܥ>BڬeOr!y(ܾ9)C XuD ]LD-zN LR,B t(_ w[ǂP&!P^}7O6` 0gTM8لRB *P4I8W;~ Y'J_o.Kf ଇZL 3az'o-`{%q)qY-08Ä'H˪gX,kJX|ɒWI)D/kJ m+{d^|H-H!( Ϋa1~,D?҂(4*-j?*doyif)ݵPʞ7AwS=VKtr,*7bKqer 9?>^7y-ࠝaKZ O#o6kqL^~-chwhA)`S&7tܕ΅"֔&+`l/[k·VZ>Ts/G` QlTڀay^l2N>E(^gHĤ5#P-dKzP`i6P\> XuD.) "o֤+*z] XuD ŷ'B!o1g^"۝rV4)%l n24%#RKJcմ}o} :<nN)!X{1߽5LGXg(R3'7MV4Lmd+Kݱm^W/JM~cy%Beѷ\䇞rB֧p> 8ܯ+Yv8Llaj]Խ_ h'gS/$[g%5݇UEȵiF4*i Ubrp2Y ~a-S aw"H Dq}( *XF n ;QjCeOLj4$rL ى5R?UB }G9KF1wH|r)1D#tv?{alzBaza6?گ_eʓbc)q;_okFStTt"gAp*0maXucvjm}3P|4ͫm)Another Testuser 8"XN   a:zd 9~l^|55/J';,s V~YAɧ^zh{C %~okIY\?Xtngb#]J%D+#^<D,Nف LnBGMr2;q {vJk؅un澹` kIWu1Iޫx|Ve8Jܪ2PY[bzޑG)>x+ʹg!foFX` "VIݝNXE~b~>"%r1adZTr1]d"(RQϟ&x~<,;#EMnhP\7QAJ҂V̵TS=-id?2'v z+}~QM"*;Du"wa_p&՟eε,!nReЋ|=VVMlȻl^+GfC`gԺP4bxB޾N~ a5w{ ]G-r XC{ 9 bY)b/@h-s#.8.sFeq 6R BPf8?)3:޲|: x,;zM1+bZRU] GKG6U@.ZWǑ=p\ XN a:-z_3&Q)>b%eYJœIn`}wVXLܳ5puIVHZL,EYc6WNgyCRQ;q<`*ٓ$<3exn&LB/t3'ԉmbt5+jTZ[o3\* BeGy].4,}R㸂!_s&@ .@~T|DQevRy>"~1ʫ'LYׂ;۫Y dkOUzhdp|Lf&cH͍xIY_/wݔHf-V26CP2И\ "_K} MaJL*`BC?glԈOP1\sC&mwuD1\_k`8|ЏJv%+yK@!'&YנK{52G 1̛h@wWj)5nu~schleuder-3.6.0/spec/fixtures/v2list_duplicate_members/random_seed000066400000000000000000000011301401002544500254610ustar00rootroot00000000000000Dw3!"\޴t^2e8+\l`~ucԇc{mPχQ#a[ qYز[,KR %M )94n2LdT  fdE}H1c:ߗ2T=ʙL6"k"h/!&JS8)=EH-&D]f TTf+Lc j`Y$Q/H/O/xz7q]8{ltST{ۢdy15`O斢/g-N,GdF'pYa!\feX,RM>K]ehH;r#$(S OHschleuder-3.6.0/spec/fixtures/v2list_duplicate_members/secring.gpg000066400000000000000000000150361401002544500254210ustar00rootroot00000000000000=XuDo)?jEFfńpH䆐mmH>RSUMbMG֜,k*'wǣ& ȅ^ncZo+őC?;5Uv*y~>`1luU{H>]XnY]bcA $Ӯn S_vXf :D(+^R 'p{u⽮er o¤15Lev%)5c1fj/[7/`€]j,^,<7SB'>A6dxއu <Ԗ9 pEpvqm!t Bf>q2nYXVg5_-zK'?::v;n;ﻄo>7Hs΅:Ӥ>1-]u`HU-qHV,@w})c sDW|i @vg(!d"'JzJ8/.y:ʦ)`?^Jx n|S2;oQ'j}|Xrp~&1OwARI\5P D'-Ag9;wK9rVvlwi }UI# Fq- SSך-Rԉl*#+n2HoXBR ®" 2]ZBLJL#+ᰝo n,?eTʩEz2oO_5ioǽ=ԋ~4qFfכ> ^[ˉ&( )nTa9ק~9n>rRѳ:ͽчPXvȿάY'aAFTFuv"㸇, z,E1px]dG@c DTJ_[bY;k "{i3[z ifʌ6σF|-ڲkķ&^&c~PNyW|I;B*x첵Z7,,0!SMύEbNfKsrw[WVn]Z|o%3)Ub`Sgela§CgOi7hZƬH3t}H<5pԈYd\Hukް;bR}>[˖Yb*PfA#.RVD# 8] v?BIRSwqΧ02݁pt<K^V̶ Dj6KW0$CI޹S5L|z N.kEJlzF¶#аU@H&L[fk; u[MaAO/qchfn-rΪҘչ&KoGE ڕ{64`pn/U@wn2&xb2}pߌ5vky/$ ۛaqnL'v^x#Sܑ~qUt/.ɩ͇GH.+o[f g荝KGxNA~&v{:"B&z8"XuD/   "o֤+*zBb7L^ 9iH,@. Ae>.*d%Cv VnOc::|{'[[ڢz\ lH'0jF̘m15{QaX 1Ҭ/Xs;9;w1l"dXPªQ ;/@e&)S{KTТYl'NGC+\y+bsOD@?&<2}d_ᛥݓ/|ktB1 9n5g DFC@TgD3<;MYV.>XXoeА9c#Z1r>Mu_Iid%s$ϛN`~T89 LL?%M;0];`ڐ/pOQ6t r8p`(eP^Td9XCJfFm:5v2 List (schleuder list) 8"XuD/   "o֤+*zk8o''%Oih|/d~*Xh˃rW3:Nhnk7#M"|~'2yZx6J~ӵyq$(LqP}6~K?@!}zW%I8 WQ5wWrzdQÅxH%Z&K^3w^rJsudV-S^e?s? gbDr=ғ:"r)qQЬgcS[asK԰]X%'@B8#1[=OZŽN>|~M9[\Nt"Gyr<;)|Iqܥ>BڬeOr!y(ܾ9)C3v2 List (schleuder list) 8"XuD/   "o֤+*zOhudX[07{-y,ry|1R*q$VQtٓO"eQ:Ǐ5?PJ`"Mq$ӳ}fD%Ezaֱ" ZęŤ-'WtWo. ȕ36Nq!X6S[u[Ӥq_yl v8hfpoQ4'<>8GhcĤPՐOP}9NZ&U\>} [m֏V*'RIK2dv&d z~*(rEWPmo-+)d *7utq!o4ׯ0 ' ,8)gb>*2>kLɒctU"wdCnPx1tG֙}@UAT<;NLl5FI-qU"c|b댷VuґkbIV4f>XuD ]LD-zN LR,B t(_ w[ǂP&!P^}7O6` 0gTM8لRB *P4I8W;~ Y'J_o.Kf ଇZL 3az'o-`{%q)qY-08Ä'H˪gX,kJX|ɒWI)D/kJ m+{d^|H-H!( Ϋa1~,D?҂(4*-j?*doyif)ݵPʞ7AwS=VKtr,*7bKqer 9?>^7y-ࠝaKZ O#o6kqL^~-chwhA)`S&7tܕ΅"֔&+`l/[k·VZ>Ts/G` QlTڀay^l2N>E(^gHĤ5#P-dKzP`i6P\.y:ʦ)`tlv90GGQFax_5p!XE,>XI**.ַ%oB0”{PmP wCBߡ%hVa1 rC`@۳U#)a.\ܦii>`C$vT:*l m/9KWپ,*#]ҍ%"p`ՏgS*fǯ"x{Ը}:5C80D`0$  mPD7 cel-(!L?eb[Ơ/'!L2ϵށ1w6cۓ_ nD$ 3v+&(TY&iu t砥)ȓw=Iaʷ$8Ѳ38ȇDGT{~:O^rWnNUAa[9${ '~w?ـkT oa`\9V tmS>}um4-J a>콉!L %sL7Z%ߚ>W;oݽq@` e3xa'w8tѰ)GO`SfSaUb%pT9kwU'b џd~bSpe|}vg6oRQ] ܙ;{B鯨܉8d`x-.8%C>7*z*gj(}fKcU LN&O-VH׫KOXt˥V,6M1|;d^P"cR_/Ŗrqae)?sMb$g'4̇!4  4A '.! 㯙g`0CT0:s,aܥ¸(#a` O|0 1xW h,/ b ԝ,Nw nx(o>_۰%:)h]&PDBUtt]aF> XuD.) "o֤+*z] XuD ŷ'B!o1g^"۝rV4)%l n24%#RKJcմ}o} :<nN)!X{1߽5LGXg(R3'7MV4Lmd+Kݱm^W/JM~cy%Beѷ\䇞rB֧p> 8ܯ+Yv8Llaj]Խ_ h'gS/$[g%5݇UEȵiF4*i Ubrp2YHߍ,R:lBuele,- zGJ2X h2 nB_!$T#|nQ\htz֫3"B,w)(1:e3:)(1:d512:S҂3LaZT)+!:fSG$$;$:[ ;_u\nnhfu>tl*Z{}:w,tdĘz,rGx6+nGaiB{"ؗm fo "ݯC;BKqп4* v 5lp I{L'˜v SM!cWs4ǜFL.;άF NW8E2J@yWP*gh}H~L._$(S"µ˜;irͣ:UX1KdQEQ(? է>T)bӐ_aG;"vihI/ QЀ 22-aii ~(х&M$7xs_|7Y}mC>Ay[_slٞDgRJvrhAjF2H14xs&A<Ϟ4RS)(1:p257:x*]nR؁FCʩ}CU~6iJk#YDŽJ4Be. } bV}|W),qJyM߂:Y@!W/?0CDgCgd Cnװ|߁oO3*)"g8=e-Tt{1C%}r#zsy zge{;fa/ 瘑@?9'pi갗ݓ|6)(1:q257:B3"7GM>sec)CsR`fGt55|D YקՇu`0ygR=$8RhIa(mS(}yNf [ cHM] Awj?k"R!R5Ɲ 4i.3MTx`^*S;LS [5M12>G&T 礙c#\}Kix*Ib]zxmĊAԁr@E҅RGj@K)(1:u257:ºhJg!>Rx TfГ¿5y\"b|D{zpn"ŒG+;!# I1%$L(z=75sIid*r~K$YWP-$"SFz cҜ]l2 m6N9DT*EOF l dmNJ+j炇nW0bb|D{zpn"ŒG+;!# I1%$L(z=75sIid*r~K$YWP-$"SFz cҜ]l2 m6N9DT*EOF l dmNJ+j炇nW0b94w!_ڱ D0?ކS7Z6锄NvX|]ct1H,=~]u %cy5D6d]Yp1قx?gI(R7Y!)j^6 6뫺,,8)θWge?,9 W8K;}KZ?0IdUmseh8).QmNEy2NkI=:i*w\xjWhD&E[p^gN1pYbk{h Y6v`0ߚgL3? %"/ό1:_257:cUZM,O&h1^iX"G7VjA+S+6ȸp)9@</d`{x{p)"9BH9wrBLVRّGJx /ISiW<8fg=Ls61Q9t%UI>xLE_{:x2sHcȴo~~u_@1Or8^=ֳ׵3G5IeYb) NFdVо/5@r"n3g#_A[1:_257:*͌KKBo*䎳k.`%$Zd[\T۷p ˨U zqqh]2}FͤZ N:2 #Z\-l'R}{W}R>Ng~UFJ#jQpt/`axKHuRU/= Chx*:BVPQ@E:ZyV*Ѣ!"ZEqփרVCkY篘I*ހIHߍ,R:lBuele,- zGJ2X h2 nB_!$T#|nQ\htz֫3"B,w*Schleuder TestUser 8"XF=   cPDuC(%_v I¸gٰd6v h+R卞]cnV2ِ7vk&@Xp)+'ƣ2N` 19GmR6NVwl]5HNUZ(Rѐ?[iZE}lZܜfA gS!'Rl)ÐdwAG%fq- goz+GxEȉN)~é[}qXh= qŊŻ1ӱt9V n2]ٖ6Q%ޛl'sqh \d_ kx妆- ?e61ƢTCv36/?[!1qDYq[X_ϱ#"ZXu-!L|ְ XF=0̖WuŊ|Cj`5T(LV4px \z|fR:ByGE=ls"7DzM֞,@~5dt2i2Y>b|D{zpn"ŒG+;!# I1%$L(z=75sIid*r~K$YWP-$"SFz cҜ]l2 m6N9DT*EOF l dmNJ+j炇nW0b0%.!8!I ,7>MJûr( G.O3\ \$-I͜mՀ h]4O@PyZqWqAkCH)C}_YLtj_̵!El.nlz/0+!$r^VkY }+ ;E/iVA%:@m:`Q;dӾ]Ѩjk}+p d#c: ߗ' a:9'\QOfs$yB32d# y'uOnBug1@rΒ4zxj> B٧?׹C\{2gG^ U ~:?Ⓙ-{ TmQKM")*]|e g.a:+nschleuder-3.6.0/spec/gnupg/random_seed000066400000000000000000000011301401002544500177410ustar00rootroot00000000000000&~)|ie/^wFQ|8$٭lad>"hȪf -d`!Qcwvc rm zi e T} W n,ʮi>riD?5b󢾭hlD0K'<5sccxYMȺA.)ƅ`6/&Y@1M)dC.Ã~~=W=,/V u)w9d%1QX JA "FA)]lMtaXL,`OXK=+3+B:|Dko^k9Ű_n, (|&r8Hߍ,R:lBuele,- zGJ2X h2 nB_!$T#|nQ\htz֫3"B,wS҂3LaZT)+!:fSG$$;$:[ ;_u\nnhfu>tl*Z{}:w,tdĘz,rGx6+nGaiB{"ؗm fo "ݯC;BKqп4* v 5lp I{L'˜v SM!cWs4ǜFL.;άF NW8E2J@yWP*gh}H~L._$(S"µ˜;irͣ:UX1KdQEQ(? է>T)bӐ_aG;"vihI/ QЀ 22-aii ~(х&M$7xs_|7Y}mC>Ay[_slٞDgRJvrhAjF2H14xs&A<Ϟ4RSx*]nR؁FCʩ}CU~6iJk#YDŽJ4Be. } bV}|W),qJyM߂:Y@!W/?0CDgCgd Cnװ|߁oO3*)"g8=e-Tt{1C%}r#zsy zge{;fa/ 瘑@?9'pi갗ݓ|6B3"7GM>sec)CsR`fGt55|D YקՇu`0ygR=$8RhIa(mS(}yNf [ cHM] Awj?k"R!R5Ɲ 4i.3MTx`^*S;LS [5M12>G&T 礙c#\}Kix*Ib]zxmĊAԁr@E҅RGj@KºhJg!>Rx TfГ¿5y\"8"XF=   cPDuC(%_v I¸gٰd6v h+R卞]cnV2ِ7vk&@Xp)+'ƣ2N` 19GmR6NVwl]5HNUZ(Rѐ?[iZE}lZܜfA gS!'Rl)ÐdwAG%fq- goz+GxEȉN)~é[}qXh= qŊŻ1ӱt9V n2]ٖ6Q%ޛl'sqh \d_ kx妆- ?e61ƢTCv36/?[!1qDYq[X_ϱ#"ZXu-!L|ְXF=0̖WuŊ|Cj`5T(LV4px \z|fR:ByGE=ls"7DzM֞,@~5dt2i2Y>b|D{zpn"ŒG+;!# I1%$L(z=75sIid*r~K$YWP-$"SFz cҜ]l2 m6N9DT*EOF l dmNJ+j炇nW0b94w!_ڱ D0?ކS7Z6锄NvX|]ct1H,=~]u %cy5D6d]Yp1قx?gI(R7Y!)j^6 6뫺,,8)θWge?,9 W8K;}KZ?0IdUmseh8).QmNEy2NkI=:i*w\xjWhD&E[p^gN1pYbk{h Y6v`0ߚgL3? %"/όcUZM,O&h1^iX"G7VjA+S+6ȸp)9@</d`{x{p)"9BH9wrBLVRّGJx /ISiW<8fg=Ls61Q9t%UI>xLE_{:x2sHcȴo~~u_@1Or8^=ֳ׵3G5IeYb) NFdVо/5@r"n3g#_A[*͌KKBo*䎳k.`%$Zd[\T۷p ˨U zqqh]2}FͤZ N:2 #Z\-l'R}{W}R>Ng~UFJ#jQpt/`axKHuRU/= Chx*:BVPQ@E:ZyV*Ѣ!"ZEqփרVCkY篘I*ހI0%.!8!I ,7>MJûr( G.O3\ \$-I͜mՀ h]4O@PyZqWqAkCH)C}_YLtj_̵!El.nlz/0+!$r^VkY }+ ;E/iVA%:@m:`Q;dӾ]Ѩjk}+p d#c: ߗ' a:9'\QOfs$yB32d# y'uOnBug1@rΒ4zxj> B٧?׹C\{2gG^ U ~:?Ⓙ-{ TmQKM")*]|e g.a:+nschleuder-3.6.0/spec/gnupg/trustdb.gpg000066400000000000000000000025201401002544500177300ustar00rootroot00000000000000gpgXFH  5^*/H_n[ `mEGρ7-xt Y"ǂYcPDu! KM'L \ 9[܇schleuder-3.6.0/spec/helpers/000077500000000000000000000000001401002544500160655ustar00rootroot00000000000000schleuder-3.6.0/spec/helpers/api_daemon_spec_helper.rb000066400000000000000000000005041401002544500230560ustar00rootroot00000000000000ENV['RACK_ENV'] = 'test' require 'spec_helper' require 'rack/test' require 'schleuder-api-daemon' module RSpecMixin include Rack::Test::Methods def app() SchleuderApiDaemon end end RSpec.configure { |c| c.include RSpecMixin } # For RSpec 2.x and 3.x def authorize! basic_authorize 'schleuder', 'test_api_key' end schleuder-3.6.0/spec/migrations/000077500000000000000000000000001401002544500165775ustar00rootroot00000000000000schleuder-3.6.0/spec/migrations/add_sig_enc_to_headers_to_meta_defaults_spec.rb000066400000000000000000000062241401002544500301550ustar00rootroot00000000000000require 'spec_helper' describe 'AddSigEncToHeadersToMetaDefaults' do let(:migrations_paths) { 'db/migrate' } let(:migration_under_test) { 20180110203100 } let(:previous_migration) { 20170713215059 } after(:each) do ActiveRecord::Migrator.migrate(migrations_paths) List.reset_column_information end describe 'up' do it 'sets the column defaults' do ActiveRecord::Migrator.migrate(migrations_paths, previous_migration) list_klass = create_list_klass list_klass.reset_column_information ActiveRecord::Migrator.migrate(migrations_paths, migration_under_test) list_klass.reset_column_information expect(list_klass.column_defaults['headers_to_meta']).to eql(["from", "to", "cc", "date", "sig", "enc"]) end it 'adds sig and enc to headers_to_meta for lists without the attributes' do ActiveRecord::Migrator.migrate(migrations_paths, previous_migration) list_klass = create_list_klass list = list_klass.create!(headers_to_meta: list_klass.column_defaults['headers_to_meta']) expect(list.headers_to_meta).not_to include('enc', 'sig') ActiveRecord::Migrator.migrate(migrations_paths, migration_under_test) list_klass.reset_column_information list.reload expect(list.headers_to_meta).to include('enc', 'sig') end it 'does not add sig and enc to headers to meta if the attributes already exist' do headers_to_meta_including_sig_and_enc = ["from", "to", "cc", "date", "sig", "enc"] ActiveRecord::Migrator.migrate(migrations_paths, previous_migration) list_klass = create_list_klass list = list_klass.create!(headers_to_meta: headers_to_meta_including_sig_and_enc) expect(list.headers_to_meta).to eql headers_to_meta_including_sig_and_enc ActiveRecord::Migrator.migrate(migrations_paths, migration_under_test) list_klass.reset_column_information list.reload expect(list.headers_to_meta).to eql headers_to_meta_including_sig_and_enc end end describe 'down' do it 'sets the column defaults' do ActiveRecord::Migrator.migrate(migrations_paths, migration_under_test) list_klass = create_list_klass list_klass.reset_column_information ActiveRecord::Migrator.migrate(migrations_paths, previous_migration) list_klass.reset_column_information expect(list_klass.column_defaults['headers_to_meta']).to eql(["from", "to", "cc", "date"]) end it 'removes sig and enc from headers_to_meta from existing lists' do ActiveRecord::Migrator.migrate(migrations_paths, migration_under_test) list_klass = create_list_klass list_klass.reset_column_information list = list_klass.create!(headers_to_meta: list_klass.column_defaults['headers_to_meta']) expect(list.headers_to_meta).to include('enc', 'sig') ActiveRecord::Migrator.migrate(migrations_paths, previous_migration) list_klass.reset_column_information list.reload expect(list.headers_to_meta).not_to include('enc', 'sig') end end def create_list_klass Class.new(ActiveRecord::Base) do self.table_name = 'lists' self.serialize :headers_to_meta, JSON end end end schleuder-3.6.0/spec/schleuder-api-daemon/000077500000000000000000000000001401002544500204115ustar00rootroot00000000000000schleuder-3.6.0/spec/schleuder-api-daemon/requests/000077500000000000000000000000001401002544500222645ustar00rootroot00000000000000schleuder-3.6.0/spec/schleuder-api-daemon/requests/authorization_spec.rb000066400000000000000000000006701401002544500265260ustar00rootroot00000000000000require 'helpers/api_daemon_spec_helper' describe 'authorization via api' do it 'allows un-authorized access to /status.json' do get '/status.json' expect(last_response).to be_ok end it 'blocks un-authorized access to other URLs' do get '/lists.json' expect(last_response.status).to be(401) end it 'allows authorized access' do authorize! get '/status.json' expect(last_response).to be_ok end end schleuder-3.6.0/spec/schleuder-api-daemon/requests/keys_spec.rb000066400000000000000000000111531401002544500245770ustar00rootroot00000000000000require 'helpers/api_daemon_spec_helper' describe 'keys via api' do before :each do @list = List.last || create(:list) end context 'list' do it 'doesn\'t list keys without authorization' do get "/keys.json?list_id=#{@list.id}" expect(last_response.status).to be 401 end it 'does list keys with authorization' do authorize! get "/keys.json?list_id=#{@list.id}" expect(last_response.status).to be 200 expect(JSON.parse(last_response.body).length).to be 1 end end context 'check' do it 'doesn\'t check keys without authorization' do get "/keys/check_keys.json?list_id=#{@list.id}" expect(last_response.status).to be 401 end it 'does check keys with authorization' do @list.import_key(File.read("spec/fixtures/revoked_key.txt")) @list.import_key(File.read("spec/fixtures/signonly_key.txt")) @list.import_key(File.read("spec/fixtures/expired_key.txt")) authorize! get "/keys/check_keys.json?list_id=#{@list.id}" expect(last_response.status).to be 200 result = JSON.parse(last_response.body)['result'] expect(result).to include("This key is expired:\n0x98769E8A1091F36BD88403ECF71A3F8412D83889") expect(result).to include("This key is revoked:\n0x7E783CDE6D1EFE6D2409739C098AC83A4C0028E9") expect(result).to include("This key is not capable of encryption:\n0xB1CD8BB15C2673C6BFD8FA4B70B2CF29E01AD53E") @list.delete_key('0x70B2CF29E01AD53E') @list.delete_key('0x098AC83A4C0028E9') @list.delete_key('0x70B2CF29E01AD53E') end end context 'export' do it 'doesn\'t export keys without authorization' do get "/keys.json?list_id=#{@list.id}" expect(last_response.status).to be 401 end it 'does list keys with authorization' do authorize! get "/keys.json?list_id=#{@list.id}" expect(last_response.status).to be 200 expect(JSON.parse(last_response.body).length).to be 1 end end context 'import' do it 'doesn\'t import keys without authorization' do parameters = {'list_id' => @list.id, 'keymaterial' => File.read('spec/fixtures/bla_foo_key.txt') } expect { post '/keys.json', parameters.to_json expect(last_response.status).to be 401 }.to change{ @list.keys.length }.by 0 end it 'does list keys with authorization' do authorize! parameters = {'list_id' => @list.id, 'keymaterial' => File.read('spec/fixtures/bla_foo_key.txt') } expect { post '/keys.json', parameters.to_json expect(last_response.status).to be 200 }.to change{ @list.keys.length }.by 1 @list.delete_key('0xEBDBE899251F2412') end end context 'delete' do before(:each) do @list.import_key(File.read("spec/fixtures/bla_foo_key.txt")) end it 'doesn\'t delete keys without authorization' do expect { delete "/keys/0xEBDBE899251F2412.json?list_id=#{@list.id}" expect(last_response.status).to be 401 }.to change{ @list.keys.length }.by 0 @list.delete_key('0xEBDBE899251F2412') end it 'does delete keys with authorization' do authorize! expect { delete "/keys/0xEBDBE899251F2412.json?list_id=#{@list.id}" expect(last_response.status).to be 200 }.to change{ @list.keys.length }.by(-1) end end context 'a key with broken utf8 in uid' do context 'already imported' do before(:each) do @list.import_key(File.read("spec/fixtures/broken_utf8_uid_key.txt")) end after(:each) do @list.delete_key('0x1242F6E13D8EBE4A') end it 'does list this key' do authorize! get "/keys.json?list_id=#{@list.id}" expect(last_response.status).to be 200 expect(JSON.parse(last_response.body).length).to be 2 end it 'does get key' do authorize! get "/keys/0x1242F6E13D8EBE4A.json?list_id=#{@list.id}" expect(last_response.status).to be 200 expect(JSON.parse(last_response.body)['fingerprint']).to eq("3102B29989BEE703AE5ED62E1242F6E13D8EBE4A") end it 'does delete key' do authorize! expect { delete "/keys/0x1242F6E13D8EBE4A.json?list_id=#{@list.id}" expect(last_response.status).to be 200 }.to change{ @list.keys.length }.by(-1) end end it 'does add key' do authorize! parameters = {'list_id' => @list.id, 'keymaterial' => File.read('spec/fixtures/broken_utf8_uid_key.txt') } expect { post '/keys.json', parameters.to_json expect(last_response.status).to be 200 }.to change{ @list.keys.length }.by(1) end end end schleuder-3.6.0/spec/schleuder-api-daemon/requests/list_spec.rb000066400000000000000000000016001401002544500245730ustar00rootroot00000000000000require 'helpers/api_daemon_spec_helper' describe 'lists via api' do it 'creates a list' do authorize! list = create(:list) parameters = { email: 'new_testlist@example.com', fingerprint: list.fingerprint } expect { post '/lists.json', parameters.to_json expect(last_response.status).to be 200 }.to change { List.count }.by 1 end it 'shows a list' do authorize! list = create(:list) get "lists/#{list.id}.json" expect(last_response.status).to be 200 expect(JSON.parse(last_response.body)['email']).to eq list.email end it 'correctly finds a list by email-address that starts with a number' do authorize! list = create(:list, email: "9list@hostname") get "lists/#{list.email}.json" expect(last_response.status).to be 200 expect(JSON.parse(last_response.body)['email']).to eq list.email end end schleuder-3.6.0/spec/schleuder-api-daemon/requests/status_spec.rb000066400000000000000000000002751401002544500251520ustar00rootroot00000000000000require 'helpers/api_daemon_spec_helper' describe 'status' do it 'returns status code 200' do authorize! get '/status.json' expect(last_response.status).to be 200 end end schleuder-3.6.0/spec/schleuder-api-daemon/requests/subscription_spec.rb000066400000000000000000000045451401002544500263570ustar00rootroot00000000000000require 'helpers/api_daemon_spec_helper' describe 'subscription via api' do before :each do @list = List.last || create(:list) @email = create(:subscription).email end it 'doesn\'t subscribe new member without authorization' do parameters = {'list_id' => @list.id, :email => @email} expect { post '/subscriptions.json', parameters.to_json expect(last_response.status).to be 401 }.to change { Subscription.count }.by 0 end it 'subscribes new member to a list' do authorize! parameters = {'list_id' => @list.id, :email => @email} expect { post '/subscriptions.json', parameters.to_json expect(last_response.status).to be 201 }.to change { Subscription.count }.by 1 expect(Subscription.where(:email => @email).first.admin?).to be false expect(Subscription.where(:email => @email).first.delivery_enabled).to be true end it 'subscribes an admin user' do authorize! parameters = {'list_id' => @list.id, :email => @email, :admin => true} expect { post '/subscriptions.json', parameters.to_json expect(last_response.status).to be 201 }.to change { Subscription.count }.by 1 expect(Subscription.where(:email => @email).first.admin?).to be true end it 'subscribes an admin user with a truthy value' do authorize! parameters = {'list_id' => @list.id, :email => @email, :admin => '1'} expect { post '/subscriptions.json', parameters.to_json expect(last_response.status).to be 201 }.to change { Subscription.count }.by 1 expect(Subscription.where(:email => @email).first.admin?).to be true end it 'subscribes an user and unsets delivery flag' do authorize! parameters = {'list_id' => @list.id, :email => @email, :delivery_enabled => false} expect { post '/subscriptions.json', parameters.to_json expect(last_response.status).to be 201 }.to change { Subscription.count }.by 1 expect(Subscription.where(:email => @email).first.delivery_enabled).to be false end it 'unsubscribes members' do authorize! subscription = create(:subscription, :list_id => @list.id) parameters = {'list_id' => @list.id, :email => @email, :delivery_enabled => false} expect { delete "/subscriptions/#{subscription.id}.json" expect(last_response.status).to be 200 }.to change { Subscription.count }.by -1 end end schleuder-3.6.0/spec/schleuder-api-daemon/requests/version_spec.rb000066400000000000000000000004341401002544500253110ustar00rootroot00000000000000require 'helpers/api_daemon_spec_helper' describe 'version' do it 'returns the current schleuder version' do authorize! get '/version.json' expect(last_response.status).to be 200 expect(last_response.body).to eq "{\"version\":\"#{Schleuder::VERSION}\"}" end end schleuder-3.6.0/spec/schleuder-certificate.pem000066400000000000000000000023611401002544500213660ustar00rootroot00000000000000-----BEGIN CERTIFICATE----- MIIDeDCCAmCgAwIBAgIBADANBgkqhkiG9w0BAQsFADA1MQswCQYDVQQGEwJNVzES MBAGA1UECgwJU2NobGV1ZGVyMRIwEAYDVQQLDAlzY2hsZXVkZXIwHhcNMTcwNjA3 MTU1NDU2WhcNMjcwNjA1MTU1NDU2WjA1MQswCQYDVQQGEwJNVzESMBAGA1UECgwJ U2NobGV1ZGVyMRIwEAYDVQQLDAlzY2hsZXVkZXIwggEiMA0GCSqGSIb3DQEBAQUA A4IBDwAwggEKAoIBAQCkEknthf/N325Yo2Vi+7JAXyewBmgAN+fQapB8KAba8BrN 8TIKi7otJ4GA2TNyYtSlXnEUslXu9YHSevDgrJpnzE0pnOmbDA21yyAZk1kG4NMO fnxw0pjyLIcOF+Do2PCI6K5ipKUZParGiBcdaJpJhRkePw5ILpGu5B3VwgLlQ+H/ vl0dC2+dLrEIVrTs5aUw5EFx/CS5i0KnYDo0K/jvDeFN2xa2tlfVOcQ9ZtVwe+Pl Rl2Kue/RcyIwfE/0M9ijys9xC7lrfmJdeBZ0i0sRoz/eTH5BAUwAGQeMAX4C58Yz qHg9WxIPUsFCvHGqIqg8IWjvfX8s2u6HEpk5HWcrAgMBAAGjgZIwgY8wDwYDVR0T AQH/BAUwAwEB/zAdBgNVHQ4EFgQUB/5P+h1owyWXwRKYnnsFrUyyYEswXQYDVR0j BFYwVIAUB/5P+h1owyWXwRKYnnsFrUyyYEuhOaQ3MDUxCzAJBgNVBAYTAk1XMRIw EAYDVQQKDAlTY2hsZXVkZXIxEjAQBgNVBAsMCXNjaGxldWRlcoIBADANBgkqhkiG 9w0BAQsFAAOCAQEAHRz4AmJWrOe9ieIh8I+qAqUsXtX9Hgh/2RvlNTNs/NvSHb8d xgrncM2ULzWeq+y7Egj61+85x2xXSplgruUFW04Rql01fzBAFafJqk2SvHEzdLIx 1mzHth/d7mFFMg0HYT4iiwhiklH3jrDJHT7EUunRQQEhgunWdXw57BiAppG2bW0U J9LHcGMsxjR6JxbgwQoCZRUBwiGAKd5P4dLc7sELx+wdjU+ChHNf2c7kzVi//Oa2 Ky7jgEuQ0TWmCzAKtx8L1WDu8x0I1QoGrUV0mLVkoCt8nPjDhbxM4hQq/QgkNZ/C wK+nz/RKC99U6r8eaofY2MJA8lr1+69JfzkelQ== -----END CERTIFICATE----- schleuder-3.6.0/spec/schleuder-private-key.pem000066400000000000000000000032171401002544500213450ustar00rootroot00000000000000-----BEGIN RSA PRIVATE KEY----- MIIEpAIBAAKCAQEApBJJ7YX/zd9uWKNlYvuyQF8nsAZoADfn0GqQfCgG2vAazfEy Cou6LSeBgNkzcmLUpV5xFLJV7vWB0nrw4KyaZ8xNKZzpmwwNtcsgGZNZBuDTDn58 cNKY8iyHDhfg6NjwiOiuYqSlGT2qxogXHWiaSYUZHj8OSC6RruQd1cIC5UPh/75d HQtvnS6xCFa07OWlMORBcfwkuYtCp2A6NCv47w3hTdsWtrZX1TnEPWbVcHvj5UZd irnv0XMiMHxP9DPYo8rPcQu5a35iXXgWdItLEaM/3kx+QQFMABkHjAF+AufGM6h4 PVsSD1LBQrxxqiKoPCFo731/LNruhxKZOR1nKwIDAQABAoIBAQCYF5wQYzdOUOCp qk5CA7Cpm4ve0RF3oltyCFcHwNMaAZnXbs9El2JumUCjgLUARD17TqDk3qxqZ4uA 4haJL3ey4OBmwt6KrBHJhBKtornUdnUv6nDQ5WiClmRb3CbRssjHIWsGZjnlvBSj FWTYDi94F7nBIBLNNt41kaFWlhK5E0fsPwd5efvNbZpJSwDPZ/iG1dwyZhCGmfu2 HeziDRDxBNDRvPFdwj2l4Oty55vqLXJuQ4nHIHk+DkPd4RtLn8xLFLdm1iFbFSFd k7/0bqpzF3+8o0lXIY3jTKH/Z1C57NAW3enjVADRuqKNZjzIsBKKCF9u/ZkfCLMC EvPlyhYBAoGBANdtJ2O4pgBho6r4Pe/iyeSTS8knr6AU+ViQMfti6qHbBH918wCa ohj5tlEovZedwaKTB58hNy6U7CT5uVK5L8LKXqBYul97ONWlSumj2J++cAsnPCyx p+zYjUm3KI/jUx/vGccOsd1eMGvhYXWBkRU9JG4qL+12W2SgE7Q+XEWxAoGBAML5 CpYt2JGE27HkQBnyaApQAARKShQhUrsHohApZpyZGkwbIqmmjEaCY1nqk70s1LLg nU1vmlnRXNetIhUcj+JtnHKJDqMEvZM/eFxQIXKdsVcD6WQf2u9ZU31TW8uH5G88 eadEHCRrTe/xvEyHlDlIXUkEJwmJDF+36QZQ/sWbAoGBAMNwA4w0uGUgL5usGoTG +uKjvt1/Y5WXcZ8nMjEeTD8Ks8nu98ZUgzqlUQHQNDCYrlMPkJqNR8K62IGzDK4/ 01Skw7Q0yuBUqfspOg082AoUexGjRrRFeFMnIwb9Y48mbQNLp9cvPa3XBZbZodE4 +qaKEcLgAxsrhT6E+1tKN+wBAoGAD5SBEREmzjIUsDlyGeCyCajs52rcUpF7H/Dz NWFpjrf5Tv2YHoBtkzDWKZhCKArOEGE8kLSLXAQL7Dwsjg1TPh/OMaTcI5C8aWjY AGBy28rYIgDxBIw7HYdA0bH4kuIQEgd+HSynJw3gE314s5Dd+lnbAnuvduaZs4hp uZR9V2MCgYB8mmk+KEiD2I3hgkBZSk6eKf1NJOrYO4xdwCb42XArERO4PtiQBdP2 VfsXhPnkkrZSDJ3/vZGw+uiI7u5UD8fl3ATIRMeYYqyiTeFM4ELPToF6hDhtcf/q l0fkQB4Je9KT8zqCDkvytvDjTTXGrxDEPTEPL1OymX4SiIRJaRSEQw== -----END RSA PRIVATE KEY----- schleuder-3.6.0/spec/schleuder.yml000066400000000000000000000006751401002544500171340ustar00rootroot00000000000000database: test: adapter: sqlite3 database: <%= ENV["SCHLEUDER_DB_PATH"] || 'db/test.sqlite3' %> lists_dir: <%= ENV["SCHLEUDER_TMP_DIR"] || '/tmp/schleuder-test/' %> listlogs_dir: <%= ENV["SCHLEUDER_TMP_DIR"] || '/tmp/schleuder-test/' %> smtp_settings: port: 2523 keyserver: hkp://localhost:9999 api: tls_cert_file: 'spec/schleuder-certificate.pem' tls_key_file: 'spec/schleuder-private-key.pem' valid_api_keys: 'test_api_key' schleuder-3.6.0/spec/schleuder/000077500000000000000000000000001401002544500164015ustar00rootroot00000000000000schleuder-3.6.0/spec/schleuder/errors_spec.rb000066400000000000000000000066041401002544500212620ustar00rootroot00000000000000require 'spec_helper' describe "Errors" do def signoff t("errors.signoff") end it "::MessageNotFromAdmin shows sensible string in response to to_s()" do expect(Errors::MessageNotFromAdmin.new.to_s).to eql(t('errors.message_not_from_admin') + signoff) end it "::MessageSenderNotSubscribed shows sensible string in response to to_s()" do expect(Errors::MessageSenderNotSubscribed.new.to_s).to eql(t('errors.message_sender_not_subscribed') + signoff) end it "::MessageUnauthenticated shows sensible string in response to to_s()" do expect(Errors::MessageUnauthenticated.new.to_s).to eql(t('errors.message_unauthenticated') + signoff) end it "::MessageUnencrypted shows sensible string in response to to_s()" do expect(Errors::MessageUnencrypted.new.to_s).to eql(t('errors.message_unencrypted') + signoff) end it "::MessageUnsigned shows sensible string in response to to_s()" do expect(Errors::MessageUnsigned.new.to_s).to eql(t('errors.message_unsigned') + signoff) end it "::LoadingListSettingsFailed shows sensible string in response to to_s()" do expect(Errors::LoadingListSettingsFailed.new.to_s).to eql(t('errors.loading_list_settings_failed', config_file: ENV['SCHLEUDER_LIST_DEFAULTS']) + signoff) end it "::DecryptionFailed shows sensible string in response to to_s()" do list = create(:list) expect(Errors::DecryptionFailed.new(list).to_s).to eql(t("errors.decryption_failed", { key: list.key.to_s, email: list.sendkey_address }) + signoff) end it "::KeyAdduidFailed shows sensible string in response to to_s()" do expect(Errors::KeyAdduidFailed.new('bla').to_s).to eql(t('errors.key_adduid_failed', { errmsg: 'bla' }) + signoff) end it "::KeyGenerationFailed shows sensible string in response to to_s()" do list = create(:list) expect(Errors::KeyGenerationFailed.new(list.listdir, list.email).to_s).to eql(t('errors.key_generation_failed', {listdir: list.listdir, listname: list.email}) + signoff) end it "::KeywordAdminOnly shows sensible string in response to to_s()" do expect(Errors::KeywordAdminOnly.new('bla').to_s).to eql(t('errors.keyword_admin_only', keyword: 'bla') + signoff) end it "::ListNotFound shows sensible string in response to to_s()" do list = create(:list) expect(Errors::ListNotFound.new(list.email).to_s).to eql(t('errors.list_not_found', email: list.email) + signoff) end it "::ListdirProblem shows sensible string in response to to_s()" do list = create(:list) expect(Errors::ListdirProblem.new(list.listdir, 'not_empty').to_s).to eql(t('errors.listdir_problem.message', dir: list.listdir, problem: t("errors.listdir_problem.not_empty")) + signoff) end it "::MessageEmpty shows sensible string in response to to_s()" do list = create(:list) expect(Errors::MessageEmpty.new(list).to_s).to eql(t('errors.message_empty', { request_address: list.request_address }) + signoff) end it "::MessageTooBig shows sensible string in response to to_s()" do list = create(:list) expect(Errors::MessageTooBig.new(list).to_s).to eql(t('errors.message_too_big', { allowed_size: list.max_message_size_kb }) + signoff) end it "::TooManyKeys shows sensible string in response to to_s()" do list = create(:list) expect(Errors::TooManyKeys.new(list.listdir, list.email).to_s).to eql(t('errors.too_many_keys', {listdir: list.listdir, listname: list.email}) + signoff) end end schleuder-3.6.0/spec/schleuder/integration/000077500000000000000000000000001401002544500207245ustar00rootroot00000000000000schleuder-3.6.0/spec/schleuder/integration/cli_spec.rb000066400000000000000000000324771401002544500230470ustar00rootroot00000000000000require "spec_helper" describe 'cli' do context "migrates a v2-list to v3.0" do it 'creates the list' do v2list_path = 'spec/fixtures/v2list' output = run_cli("migrate #{v2list_path}") list = Schleuder::List.by_recipient('v2list@example.org') expect(output).to be_present expect(list).to be_present end it "imports the public keys" do v2list_path = 'spec/fixtures/v2list' output = run_cli("migrate #{v2list_path}") list = Schleuder::List.by_recipient('v2list@example.org') expect(output).not_to match('Error:') keys = list.keys.map(&:fingerprint) expect(list.key.fingerprint).to eq '0392CF72B345256BB730049789226FD6A42B2A7A' expect(keys).to include 'C4D60F8833789C7CAA44496FD3FFA6613AB10ECE' end it "imports the secret key" do v2list_path = 'spec/fixtures/v2list' output = run_cli("migrate #{v2list_path}") list = Schleuder::List.by_recipient('v2list@example.org') expect(output).not_to match('Error:') expect(list.secret_key).to be_present expect(list.secret_key.fingerprint).to eq '0392CF72B345256BB730049789226FD6A42B2A7A' signed = GPGME::Crypto.new(:armor => true).clearsign('lala').read expect(signed).to match(/^-----BEGIN PGP SIGNED MESSAGE-----\n.*\n\nlala\n-----BEGIN PGP SIGNATURE-----\n.*\n-----END PGP SIGNATURE-----\n$/m) end it "imports the config" do v2list_path = 'spec/fixtures/v2list' output = run_cli("migrate #{v2list_path}") list = Schleuder::List.by_recipient('v2list@example.org') expect(output).not_to match('Error:') expect(list.to_s).to eq 'v2list@example.org' expect(list.log_level).to eq 'warn' expect(list.fingerprint).to eq '0392CF72B345256BB730049789226FD6A42B2A7A' expect(list.keywords_admin_only).to eq %w[subscribe unsubscribe delete-key] expect(list.keywords_admin_notify).to eq %w[add-key unsubscribe] expect(list.send_encrypted_only).to eq false expect(list.receive_encrypted_only).to eq false expect(list.receive_signed_only).to eq false expect(list.receive_authenticated_only).to eq false expect(list.receive_from_subscribed_emailaddresses_only).to eq false expect(list.receive_admin_only).to eq false expect(list.keep_msgid).to eq true expect(list.bounces_drop_all).to eq false expect(list.bounces_notify_admins).to eq true expect(list.deliver_selfsent).to eq true expect(list.include_list_headers).to eq true expect(list.include_openpgp_header).to eq true expect(list.openpgp_header_preference).to eq 'signencrypt' expect(list.headers_to_meta).to eq %w[from to cc date] expect(list.bounces_drop_on_headers).to eq({'x-spam-flag' => "yes"}) expect(list.subject_prefix).to eq '[v2]' expect(list.subject_prefix_in).to eq '[in]' expect(list.subject_prefix_out).to eq '[out]' expect(list.max_message_size_kb).to eq 10240 expect(list.public_footer).to eq "-- \nfooter" expect(list.internal_footer).to be_nil end it "imports the subscriptions" do v2list_path = 'spec/fixtures/v2list' output = run_cli("migrate #{v2list_path}") list = Schleuder::List.by_recipient('v2list@example.org') admins_emails = list.admins.map(&:email) subscription_emails = list.subscriptions.map(&:email) expect(output).not_to match('Error:') expect(admins_emails).to eql(["schleuder2@example.org"]) expect(subscription_emails).to eql(["anotherone@example.org", "anyone@example.org", "bla@foo", "old@example.org", "schleuder2@example.org", "someone@example.org"]) expect(list.subscriptions.where(email: "anotherone@example.org").first.fingerprint).to eql('') expect(list.subscriptions.where(email: "anyone@example.org").first.fingerprint).to eql("C4D60F8833789C7CAA44496FD3FFA6613AB10ECE") expect(list.subscriptions.where(email: "bla@foo").first.fingerprint).to eql("87E65ED2081AE3D16BE4F0A5EBDBE899251F2412") expect(list.subscriptions.where(email: "old@example.org").first.fingerprint).to eql("6EE51D78FD0B33DE65CCF69D2104E20E20889F66") expect(list.subscriptions.where(email: "schleuder2@example.org").first.fingerprint).to eql("C4D60F8833789C7CAA44496FD3FFA6613AB10ECE") expect(list.subscriptions.where(email: "someone@example.org").first.fingerprint).to eql('') end it "does not fail on duplicated v2 subscriptions" do v2list_path = 'spec/fixtures/v2list_duplicate_members' output = run_cli("migrate #{v2list_path}") expect(output).not_to match('Error:') list = Schleuder::List.by_recipient('v2list@example.org') subscription_emails = list.subscriptions.map(&:email) expect(subscription_emails).to eq ['schleuder2@example.org'] end it "respects non delivery status of admins" do v2list_path = 'spec/fixtures/v2list_admin_non_delivery' output = run_cli("migrate #{v2list_path}") expect(output).not_to match('Error:') list = Schleuder::List.by_recipient('v2list@example.org') subscriptions = list.subscriptions expect(subscriptions.find{|s| s.email == 'schleuder2@example.org' }.delivery_enabled).to eq false subscription_emails = subscriptions.map(&:email) expect(subscription_emails.sort).to eq(['schleuder2@example.org', 'schleuder2-member@example.org'].sort) end it "does not fail on admin without key" do v2list_path = 'spec/fixtures/v2list_admin_without_key' output = run_cli("migrate #{v2list_path}") expect(output).not_to match('Error:') list = Schleuder::List.by_recipient('v2list@example.org') admin_emails = list.admins.map(&:email) expect(admin_emails.sort).to eq( ['schleuder2@example.org', 'schleuder2-nokey@example.org' ].sort) end it "warns about file system permissions if it was run as root" do expect(Process).to receive(:euid).and_return(0) v2list_path = 'spec/fixtures/v2list' orig_stdout = $stdout $stdout = StringIO.new Cli.new.migrate_v2_list(v2list_path) output = $stdout.string $stdout = orig_stdout expect(output).to include("Warning: this process was run as root") end end context '#refresh_keys' do it 'updates keys from the keyserver' do list = create(:list) list.subscribe("admin@example.org", nil, true) list.import_key(File.read("spec/fixtures/expired_key.txt")) list.import_key(File.read("spec/fixtures/olduid_key.txt")) with_sks_mock(list.listdir) do Cli.new.refresh_keys dirmngr_pid = `pgrep -a dirmngr | grep #{list.listdir}`.split(' ',2).first expect(dirmngr_pid).to be_nil end mail = Mail::TestMailer.deliveries.find { |message| message.to == [list.admins.first.email] } b = mail.first_plaintext_part.body.to_s expect(b).to match(/Refreshing all keys from the keyring of list #{list.email} resulted in this:\n\n/) expect(b).to match(/\nThis key was updated \(new signatures\):\n0x98769E8A1091F36BD88403ECF71A3F8412D83889 bla@foo \d{4}-\d{2}-\d{2} \[expired: \d{4}-\d{2}-\d{2}\]\n/) expect(b).to match(/\nThis key was updated \(new user-IDs and new signatures\):\n0x6EE51D78FD0B33DE65CCF69D2104E20E20889F66 new@example.org \d{4}-\d{2}-\d{2}\n/) teardown_list_and_mailer(list) end it 'updates keys from the keyserver for only a specific list' do list1 = create(:list) list2 = create(:list) [list1,list2].each do |list| list.subscribe("admin@example.org", nil, true) list.import_key(File.read("spec/fixtures/expired_key.txt")) list.import_key(File.read("spec/fixtures/olduid_key.txt")) end with_sks_mock(list1.listdir) do Cli.new.refresh_keys list1.email end mail = Mail::TestMailer.deliveries.find { |message| message.to == [list1.admins.first.email] } b = mail.first_plaintext_part.body.to_s expect(b).to match(/Refreshing all keys from the keyring of list #{list1.email} resulted in this:\n\n/) expect(b).to match(/\nThis key was updated \(new signatures\):\n0x98769E8A1091F36BD88403ECF71A3F8412D83889 bla@foo \d{4}-\d{2}-\d{2} \[expired: \d{4}-\d{2}-\d{2}\]\n/) expect(b).to match(/\nThis key was updated \(new user-IDs and new signatures\):\n0x6EE51D78FD0B33DE65CCF69D2104E20E20889F66 new@example.org \d{4}-\d{2}-\d{2}\n/) teardown_list_and_mailer(list1) teardown_list_and_mailer(list2) end it 'reports errors from refreshing keys' do list = create(:list) list.subscribe("admin@example.org", nil, true) list.import_key(File.read("spec/fixtures/expired_key.txt")) Cli.new.refresh_keys mail = Mail::TestMailer.deliveries.find { |message| message.to == [list.admins.first.email] } expect(mail.to_s).to include("Refreshing all keys from the keyring of list #{list.email} resulted in this") if GPGME::Ctx.sufficient_gpg_version?('2.1') expect(mail.to_s).to include("keyserver refresh failed:") else # The wording differs slightly among versions. expect(mail.to_s).to match(/gpgkeys: .* error .* connect/) end teardown_list_and_mailer(list) end it "warns about file system permissions if it was run as root" do expect(Process).to receive(:euid).and_return(0) list = create(:list) orig_stdout = $stdout $stdout = StringIO.new Cli.new.refresh_keys(list.email) output = $stdout.string $stdout = orig_stdout expect(output).to include("Warning: this process was run as root") end end context '#pin_keys' do it 'pins fingerprints on not yet set keys' do list = create(:list) list.subscribe("admin@example.org", nil, true) list.subscribe("schleuder2@example.org", nil, false) list.import_key(File.read('spec/fixtures/example_key.txt')) expect(list.subscriptions_without_fingerprint.size).to eq 2 Cli.new.pin_keys expect(list.subscriptions_without_fingerprint.size).to eq 1 expect(list.subscriptions_without_fingerprint.collect(&:email)).to eq ['admin@example.org'] mail = Mail::TestMailer.deliveries.first expect(Mail::TestMailer.deliveries.length).to eq 1 expect(mail.first_plaintext_part.body.to_s).to eql("While checking all subscriptions of list #{list.email} we were pinning a matching key for the following subscriptions:\n\nschleuder2@example.org: C4D60F8833789C7CAA44496FD3FFA6613AB10ECE") teardown_list_and_mailer(list) end it 'only works on the specific list' do list1 = create(:list) list2 = create(:list) [list1,list2].each do |list| list.subscribe("admin@example.org", nil, true) list.subscribe("schleuder2@example.org", nil, false) list.import_key(File.read('spec/fixtures/example_key.txt')) expect(list.subscriptions_without_fingerprint.size).to eq 2 end Cli.new.pin_keys list1.email expect(list1.subscriptions_without_fingerprint.size).to eq 1 expect(list1.subscriptions_without_fingerprint.collect(&:email)).to eq ['admin@example.org'] expect(list2.subscriptions_without_fingerprint.size).to eq 2 mail = Mail::TestMailer.deliveries.first expect(Mail::TestMailer.deliveries.length).to eq 1 expect(mail.first_plaintext_part.body.to_s).to eql("While checking all subscriptions of list #{list1.email} we were pinning a matching key for the following subscriptions:\n\nschleuder2@example.org: C4D60F8833789C7CAA44496FD3FFA6613AB10ECE") teardown_list_and_mailer(list1) teardown_list_and_mailer(list2) end it 'does not report anything if nothing was done' do list = create(:list) list.subscribe("admin@example.org", nil, true) list.subscribe("schleuder2@example.org", nil, false) expect(list.subscriptions_without_fingerprint.size).to eq 2 Cli.new.pin_keys expect(list.subscriptions_without_fingerprint.size).to eq 2 expect(Mail::TestMailer.deliveries.empty?).to eq true teardown_list_and_mailer(list) end end context '#install' do it 'exits if a shell-process failed' do dbfile = Conf.database["database"] tmp_filename = "#{dbfile}.tmp" File.rename(dbfile, tmp_filename) FileUtils.touch dbfile begin Cli.new.install rescue SystemExit => exc end expect(exc).to be_present expect(exc.status).to eql(1) File.rename(tmp_filename, dbfile) end it "warns about file system permissions if it was run as root" do expect(Process).to receive(:euid).and_return(0) orig_stdout = $stdout $stdout = StringIO.new Cli.new.install output = $stdout.string $stdout = orig_stdout expect(output).to include("Warning: this process was run as root") end end context '#commands' do it 'exits with a status code of 1 in case the command is not implemented' do run_cli('not-implemented') expect($?.exitstatus).to eq(1) end end context '#check_keys' do it "warns about file system permissions if it was run as root" do expect(Process).to receive(:euid).and_return(0) orig_stdout = $stdout $stdout = StringIO.new Cli.new.check_keys output = $stdout.string $stdout = orig_stdout expect(output).to include("Warning: this process was run as root") end end end schleuder-3.6.0/spec/schleuder/integration/dash_addresses_spec.rb000066400000000000000000000124511401002544500252420ustar00rootroot00000000000000require "spec_helper" describe 'someone sends an email to a listname-dash-address' do it "sends the list's key as reply to -sendkey" do list = create(:list) list.subscribe("schleuder@example.org", nil, true) ENV['GNUPGHOME'] = list.listdir mail = Mail.new mail.to = list.sendkey_address mail.from = 'outside@example.org' mail.body = 'The key, please!' mail.subject = 'key' mail.deliver mail = Mail::TestMailer.deliveries.first Mail::TestMailer.deliveries.clear output = process_mail(mail.to_s, list.sendkey_address) expect(output).to be_nil message = Mail::TestMailer.deliveries.first expect(message.to).to eql(['outside@example.org']) signed_message_parts = message.parts[0].parts expect(signed_message_parts.first.body.to_s).to eql('Find the key for this address attached.') expect(message.parts[0].attachments.first.body.to_s).to include(list.fingerprint) expect(message.parts[0].attachments.first.body.to_s).to include('-----BEGIN PGP PUBLIC KEY BLOCK-----') expect(message.in_reply_to).to eql(mail.message_id) end it "forwards the message to the admins if extension is -owner" do list = create(:list) # owner needs a key so they get email list.subscribe("schleuder@example.org", '59C71FB38AEE22E091C78259D06350440F759BD3', true) list.subscribe("admin@example.org", '59C71FB38AEE22E091C78259D06350440F759BD3', true) ENV['GNUPGHOME'] = list.listdir mail = Mail.new mail.to = list.owner_address mail.from = 'outside@example.org' mail.body = 'Please contact me directly!' mail.subject = 'help' mail.deliver mail = Mail::TestMailer.deliveries.first Mail::TestMailer.deliveries.clear output = process_mail(mail.to_s, list.owner_address) expect(output).to be_nil raw_msgs = Mail::TestMailer.deliveries raw_msgs.sort_by { |msg| msg.to.first } # reparse the messages so we decrypt and remove all the craft # for easier parsing afterwards message1, message2 = raw_msgs[0..1].collect{|m| Mail.create_message_to_list(m.to_s, list.email, list).setup } expect(message1.to).to eql(['admin@example.org']) expect(message1.subject).to eql('help') expect(message1.parts.first.body.to_s).to include('From: outside@example.org') expect(message1.parts.first.body.to_s).to include('Note: The following message was received for the list-owners.') expect(message1.parts.last.body.to_s).to eql('Please contact me directly!') expect(message2.to).to eql(['schleuder@example.org']) expect(message2.subject).to eql('help') expect(message2.parts.first.body.to_s).to include('From: outside@example.org') expect(message2.parts.first.body.to_s).to include('Note: The following message was received for the list-owners.') expect(message2.parts.last.body.to_s).to eql('Please contact me directly!') end it "forwards the message to the admins if extension is -bounce" do list = create(:list) list.subscribe("admin@example.org", nil, true) ENV['GNUPGHOME'] = list.listdir mail = Mail.new mail.to = list.bounce_address mail.from = 'mailer-daemon@example.org' mail.body = 'delivery failure' mail.subject = 'something' mail.deliver mail = Mail::TestMailer.deliveries.first Mail::TestMailer.deliveries.clear output = process_mail(mail.to_s, list.bounce_address) expect(output).to be_nil message = Mail::TestMailer.deliveries.first expect(message.to).to eql(['admin@example.org']) expect(message.subject).to eql(I18n.t('automated_message_subject')) signed_message_parts = message.parts[0].parts expect(signed_message_parts.first.body.to_s).to eql(I18n.t('forward_automated_message_to_admins')) expect(signed_message_parts.last.mime_type).to eql('message/rfc822') expect(signed_message_parts.last.body.to_s).to include('From: mailer-daemon@example.org') expect(signed_message_parts.last.body.to_s).to include(mail.message_id) expect(signed_message_parts.last.body.to_s).to include("Subject: something") expect(signed_message_parts.last.body.to_s).to include("delivery failure") end it "forwards the message to the admins if extension is -bounce and it's a real bounce mail" do list = create(:list) list.subscribe("admin@example.org", nil, true) ENV['GNUPGHOME'] = list.listdir mail = Mail.new(File.read('spec/fixtures/mails/bounce.eml')) mail.to = list.owner_address mail.deliver mail = Mail::TestMailer.deliveries.first Mail::TestMailer.deliveries.clear output = process_mail(mail.to_s, list.bounce_address) expect(output).to be_nil message = Mail::TestMailer.deliveries.first expect(message.to).to eql(['admin@example.org']) expect(message.subject).to eql(I18n.t('automated_message_subject')) signed_message_parts = message.parts[0].parts expect(signed_message_parts.first.body.to_s).to eql(I18n.t('forward_automated_message_to_admins')) expect(signed_message_parts.last.mime_type).to eql('message/rfc822') expect(signed_message_parts.last.body.to_s).to include('Mailer-Daemon@schleuder.example.org') expect(signed_message_parts.last.body.to_s).to include(mail.message_id) expect(signed_message_parts.last.body.to_s).to include("Subject: bounce test") expect(signed_message_parts.last.body.to_s).to include("mailbox is full") end end schleuder-3.6.0/spec/schleuder/integration/filters_spec.rb000066400000000000000000000117711401002544500237420ustar00rootroot00000000000000require "spec_helper" describe "running filters" do context '.max_message_size' do it "bounces to big mails" do list = create(:list) list.subscribe("schleuder@example.org", '59C71FB38AEE22E091C78259D06350440F759BD3', true) ENV['GNUPGHOME'] = list.listdir mail = Mail.new mail.to = list.request_address mail.from = list.admins.first.email gpg_opts = { encrypt: true, keys: {list.request_address => list.fingerprint}, sign: true, sign_as: list.admins.first.fingerprint } mail.gpg(gpg_opts) mail.body = '+' * (1024 * list.max_message_size_kb) mail.deliver big_email = Mail::TestMailer.deliveries.first Mail::TestMailer.deliveries.clear output = process_mail(big_email.to_s, list.email) expect(output.message).to include(I18n.t('errors.message_too_big', { allowed_size: list.max_message_size_kb })) teardown_list_and_mailer(list) end end context '.fix_exchange_messages!' do it "accepts an invalid pgp/mime Exchange message" do list = create(:list) list.subscribe("admin@example.org", nil, true) # so we can easily parse the outgoing mail list.send_encrypted_only = false list.save start_smtp_daemon message_path = 'spec/fixtures/mails/exchange.eml' error = run_schleuder(:work, list.email, message_path) mails = Dir.glob("#{smtp_daemon_outputdir}/mail-*") expect(error).to be_empty expect(mails.size).to eq 1 exchange = Mail.read(mails.first) expect(exchange.to).to eql(["admin@example.org"]) expect(exchange.body.to_s).to include("foo\n") stop_smtp_daemon end it "accepts a valid plain-text message" do list = create(:list) list.subscribe("admin@example.org", nil, true) # so we can easily parse the outgoing mail list.send_encrypted_only = false list.save start_smtp_daemon message_path = 'spec/fixtures/mails/exchange_no_parts.eml' error = run_schleuder(:work, list.email, message_path) mails = Dir.glob("#{smtp_daemon_outputdir}/mail-*") expect(error).to be_empty expect(mails.size).to eq 1 exchange = Mail.read(mails.first) expect(exchange.to).to eql(["admin@example.org"]) expect(exchange.body.to_s).to include("bla-vla") stop_smtp_daemon end end context '.strip_html_from_alternative!' do it "strips HTML-part from multipart/alternative-message that contains ascii-armored PGP-data" do list = create(:list) list.subscribe("admin@example.org", nil, true) # so we can easily parse the outgoing mail list.send_encrypted_only = false list.save start_smtp_daemon mail = Mail.new mail.to = list.email mail.from = 'outside@example.org' content = encrypt_string(list, "blabla") mail.text_part = content mail.html_part = "

#{content}

" mail.subject = "test" error = nil with_tmpfile(mail.to_s) do |fn| error = run_schleuder(:work, list.email, fn) end mails = Dir.glob("#{smtp_daemon_outputdir}/mail-*") expect(error).to be_empty expect(mails.size).to eq 1 htmlmail = Mail.read(mails.first) expect(htmlmail.to).to eql(["admin@example.org"]) signed_parts = htmlmail.parts[0].parts expect(signed_parts[0].body.to_s).to include("Note: This message included an alternating HTML-part that contained\n PGP-data. The HTML-part was removed to enable parsing the message more\n properly.\n") # why is this double wrapped? expect(signed_parts[1].parts[0][:content_type].content_type).to eql("text/plain") expect(signed_parts[1].parts[0].body.to_s).to eql("blabla\n") stop_smtp_daemon end it "does NOT strip HTML-part from multipart/alternative-message that does NOT contain ascii-armored PGP-data" do list = create(:list) list.subscribe("admin@example.org", nil, true) # so we can easily parse the outgoing mail list.send_encrypted_only = false list.save start_smtp_daemon mail = Mail.new mail.to = list.email mail.from = 'outside@example.org' content = "blabla" mail.text_part = content mail.html_part = "

#{content}

" mail.subject = "test" error = nil with_tmpfile(mail.to_s) do |fn| error = run_schleuder(:work, list.email, fn) end mails = Dir.glob("#{smtp_daemon_outputdir}/mail-*") expect(error).to be_empty expect(mails.size).to eq 1 htmlmail = Mail.read(mails.first) expect(htmlmail.to).to eql(["admin@example.org"]) # this is double wrapped signed_parts = htmlmail.parts[0].parts[1].parts expect(signed_parts[0][:content_type].content_type).to eql("text/plain") expect(signed_parts[0].body.to_s).to eql("blabla") expect(signed_parts[1][:content_type].content_type).to eql("text/html") expect(signed_parts[1].body.to_s).to eql("

blabla

") stop_smtp_daemon end end end schleuder-3.6.0/spec/schleuder/integration/keywords_spec.rb000066400000000000000000004000011401002544500241250ustar00rootroot00000000000000# coding: utf-8 require "spec_helper" describe "user sends keyword" do it "x-subscribe without attributes" do list = create(:list) list.subscribe("schleuder@example.org", '59C71FB38AEE22E091C78259D06350440F759BD3', true) ENV['GNUPGHOME'] = list.listdir mail = Mail.new mail.to = list.request_address mail.from = list.admins.first.email gpg_opts = { encrypt: true, keys: {list.request_address => list.fingerprint}, sign: true, sign_as: list.admins.first.fingerprint } mail.gpg(gpg_opts) mail.body = "x-list-name: #{list.email}\nX-SUBSCRIBE: test@example.org" mail.deliver encrypted_mail = Mail::TestMailer.deliveries.first Mail::TestMailer.deliveries.clear begin Schleuder::Runner.new().run(encrypted_mail.to_s, list.request_address) rescue SystemExit end raw = Mail::TestMailer.deliveries.first message = Mail.create_message_to_list(raw.to_s, list.request_address, list).setup subscription = list.subscriptions.where(email: 'test@example.org').first expect(message.to).to eql(['schleuder@example.org']) expect(message.to_s).to include("test@example.org has been subscribed") expect(message.to_s).to match(/Fingerprint:\s*$/) expect(message.to_s).to include("Admin? false") expect(message.to_s).to include("Email-delivery enabled? true") expect(subscription).to be_present expect(subscription.fingerprint).to be_blank expect(subscription.admin).to eql(false) expect(subscription.delivery_enabled).to eql(true) teardown_list_and_mailer(list) end it "x-subscribe with attributes" do list = create(:list) list.subscribe("schleuder@example.org", '59C71FB38AEE22E091C78259D06350440F759BD3', true) ENV['GNUPGHOME'] = list.listdir mail = Mail.new mail.to = list.request_address mail.from = list.admins.first.email gpg_opts = { encrypt: true, keys: {list.request_address => list.fingerprint}, sign: true, sign_as: list.admins.first.fingerprint } mail.gpg(gpg_opts) mail.body = "x-list-name: #{list.email}\nX-SUBSCRIBE: test@example.org 0x#{list.fingerprint} true false" mail.deliver encrypted_mail = Mail::TestMailer.deliveries.first Mail::TestMailer.deliveries.clear begin Schleuder::Runner.new().run(encrypted_mail.to_s, list.request_address) rescue SystemExit end raw = Mail::TestMailer.deliveries.first message = Mail.create_message_to_list(raw.to_s, list.request_address, list).setup subscription = list.subscriptions.where(email: 'test@example.org').first expect(message.to).to eql(['schleuder@example.org']) expect(message.to_s).to include("test@example.org has been subscribed") expect(message.to_s).to match(/Fingerprint:\s+#{list.fingerprint}/) expect(message.to_s).to include("Admin? true") expect(message.to_s).to include("Email-delivery enabled? false") expect(subscription).to be_present expect(subscription.fingerprint).to eql(list.fingerprint) expect(subscription.admin).to eql(true) expect(subscription.delivery_enabled).to eql(false) teardown_list_and_mailer(list) end it "x-subscribe with one attribute and spaces-separated fingerprint" do list = create(:list) list.subscribe("schleuder@example.org", '59C71FB38AEE22E091C78259D06350440F759BD3', true) ENV['GNUPGHOME'] = list.listdir mail = Mail.new mail.to = list.request_address mail.from = list.admins.first.email gpg_opts = { encrypt: true, keys: {list.request_address => list.fingerprint}, sign: true, sign_as: list.admins.first.fingerprint } mail.gpg(gpg_opts) mail.body = "x-list-name: #{list.email}\nX-SUBSCRIBE: test@example.org 0x#{list.fingerprint.dup.insert(4, ' ')} true" mail.deliver encrypted_mail = Mail::TestMailer.deliveries.first Mail::TestMailer.deliveries.clear begin Schleuder::Runner.new().run(encrypted_mail.to_s, list.request_address) rescue SystemExit end raw = Mail::TestMailer.deliveries.first message = Mail.create_message_to_list(raw.to_s, list.request_address, list).setup subscription = list.subscriptions.where(email: 'test@example.org').first expect(message.to).to eql(['schleuder@example.org']) expect(message.to_s).to include("test@example.org has been subscribed") expect(message.to_s).to match(/Fingerprint:\s+#{list.fingerprint}/) expect(message.to_s).to include("Admin? true") expect(message.to_s).to include("Email-delivery enabled? true") expect(subscription).to be_present expect(subscription.fingerprint).to eql(list.fingerprint) expect(subscription.admin).to eql(true) expect(subscription.delivery_enabled).to eql(true) teardown_list_and_mailer(list) end it "x-subscribe without attributes, but with spaces-separated fingerprint" do list = create(:list) list.subscribe("schleuder@example.org", '59C71FB38AEE22E091C78259D06350440F759BD3', true) ENV['GNUPGHOME'] = list.listdir mail = Mail.new mail.to = list.request_address mail.from = list.admins.first.email gpg_opts = { encrypt: true, keys: {list.request_address => list.fingerprint}, sign: true, sign_as: list.admins.first.fingerprint } mail.gpg(gpg_opts) mail.body = "x-list-name: #{list.email}\nX-SUBSCRIBE: test@example.org 0x#{list.fingerprint.dup.insert(4, ' ')}" mail.deliver encrypted_mail = Mail::TestMailer.deliveries.first Mail::TestMailer.deliveries.clear begin Schleuder::Runner.new().run(encrypted_mail.to_s, list.request_address) rescue SystemExit end raw = Mail::TestMailer.deliveries.first message = Mail.create_message_to_list(raw.to_s, list.request_address, list).setup subscription = list.subscriptions.where(email: 'test@example.org').first expect(message.to).to eql(['schleuder@example.org']) expect(message.to_s).to include("test@example.org has been subscribed") expect(message.to_s).to match(/Fingerprint:\s+#{list.fingerprint}/) expect(message.to_s).to include("Admin? false") expect(message.to_s).to include("Email-delivery enabled? true") expect(subscription).to be_present expect(subscription.fingerprint).to eql(list.fingerprint) expect(subscription.admin).to eql(false) expect(subscription.delivery_enabled).to eql(true) teardown_list_and_mailer(list) end it "x-subscribe with attributes and spaces-separated fingerprint" do list = create(:list) list.subscribe("schleuder@example.org", '59C71FB38AEE22E091C78259D06350440F759BD3', true) ENV['GNUPGHOME'] = list.listdir mail = Mail.new mail.to = list.request_address mail.from = list.admins.first.email gpg_opts = { encrypt: true, keys: {list.request_address => list.fingerprint}, sign: true, sign_as: list.admins.first.fingerprint } mail.gpg(gpg_opts) mail.body = "x-list-name: #{list.email}\nX-SUBSCRIBE: test@example.org 0x#{list.fingerprint.dup.insert(4, ' ')} true false" mail.deliver encrypted_mail = Mail::TestMailer.deliveries.first Mail::TestMailer.deliveries.clear begin Schleuder::Runner.new().run(encrypted_mail.to_s, list.request_address) rescue SystemExit end raw = Mail::TestMailer.deliveries.first message = Mail.create_message_to_list(raw.to_s, list.request_address, list).setup subscription = list.subscriptions.where(email: 'test@example.org').first expect(message.to).to eql(['schleuder@example.org']) expect(message.to_s).to include("test@example.org has been subscribed") expect(message.to_s).to match(/Fingerprint:\s+#{list.fingerprint}/) expect(message.to_s).to include("Admin? true") expect(message.to_s).to include("Email-delivery enabled? false") expect(subscription).to be_present expect(subscription.fingerprint).to eql(list.fingerprint) expect(subscription.admin).to eql(true) expect(subscription.delivery_enabled).to eql(false) teardown_list_and_mailer(list) end it "x-subscribe with attributes (first one 'false') and spaces-separated fingerprint" do list = create(:list) list.subscribe("schleuder@example.org", '59C71FB38AEE22E091C78259D06350440F759BD3', true) ENV['GNUPGHOME'] = list.listdir mail = Mail.new mail.to = list.request_address mail.from = list.admins.first.email gpg_opts = { encrypt: true, keys: {list.request_address => list.fingerprint}, sign: true, sign_as: list.admins.first.fingerprint } mail.gpg(gpg_opts) mail.body = "x-list-name: #{list.email}\nX-SUBSCRIBE: test@example.org 0x#{list.fingerprint.dup.insert(4, ' ')} false false" mail.deliver encrypted_mail = Mail::TestMailer.deliveries.first Mail::TestMailer.deliveries.clear begin Schleuder::Runner.new().run(encrypted_mail.to_s, list.request_address) rescue SystemExit end raw = Mail::TestMailer.deliveries.first message = Mail.create_message_to_list(raw.to_s, list.request_address, list).setup subscription = list.subscriptions.where(email: 'test@example.org').first expect(message.to).to eql(['schleuder@example.org']) expect(message.to_s).to include("test@example.org has been subscribed") expect(message.to_s).to match(/Fingerprint:\s+#{list.fingerprint}/) expect(message.to_s).to include("Admin? false") expect(message.to_s).to include("Email-delivery enabled? false") expect(subscription).to be_present expect(subscription.fingerprint).to eql(list.fingerprint) expect(subscription.admin).to eql(false) expect(subscription.delivery_enabled).to eql(false) teardown_list_and_mailer(list) end it "x-subscribe with attributes (last one 'true') and spaces-separated fingerprint" do list = create(:list) list.subscribe("schleuder@example.org", '59C71FB38AEE22E091C78259D06350440F759BD3', true) ENV['GNUPGHOME'] = list.listdir mail = Mail.new mail.to = list.request_address mail.from = list.admins.first.email gpg_opts = { encrypt: true, keys: {list.request_address => list.fingerprint}, sign: true, sign_as: list.admins.first.fingerprint } mail.gpg(gpg_opts) mail.body = "x-list-name: #{list.email}\nX-SUBSCRIBE: test@example.org 0x#{list.fingerprint.dup.insert(4, ' ')} false true" mail.deliver encrypted_mail = Mail::TestMailer.deliveries.first Mail::TestMailer.deliveries.clear begin Schleuder::Runner.new().run(encrypted_mail.to_s, list.request_address) rescue SystemExit end raw = Mail::TestMailer.deliveries.first message = Mail.create_message_to_list(raw.to_s, list.request_address, list).setup subscription = list.subscriptions.where(email: 'test@example.org').first expect(message.to).to eql(['schleuder@example.org']) expect(message.to_s).to include("test@example.org has been subscribed") expect(message.to_s).to match(/Fingerprint:\s+#{list.fingerprint}/) expect(message.to_s).to include("Admin? false") expect(message.to_s).to include("Email-delivery enabled? true") expect(subscription).to be_present expect(subscription.fingerprint).to eql(list.fingerprint) expect(subscription.admin).to eql(false) expect(subscription.delivery_enabled).to eql(true) teardown_list_and_mailer(list) end it "x-subscribe without arguments" do list = create(:list) list.subscribe("schleuder@example.org", '59C71FB38AEE22E091C78259D06350440F759BD3', true) ENV['GNUPGHOME'] = list.listdir mail = Mail.new mail.to = list.request_address mail.from = list.admins.first.email gpg_opts = { encrypt: true, keys: {list.request_address => list.fingerprint}, sign: true, sign_as: list.admins.first.fingerprint } mail.gpg(gpg_opts) mail.body = "x-list-name: #{list.email}\nX-SUBSCRIBE:" mail.deliver encrypted_mail = Mail::TestMailer.deliveries.first Mail::TestMailer.deliveries.clear begin Schleuder::Runner.new().run(encrypted_mail.to_s, list.request_address) rescue SystemExit end raw = Mail::TestMailer.deliveries.first message = Mail.create_message_to_list(raw.to_s, list.request_address, list).setup subscription = list.subscriptions.where(email: 'test@example.org').first expect(message.to).to eql(['schleuder@example.org']) expect(message.to_s).not_to include("translation missing") expect(message.first_plaintext_part.body.to_s).to eql(I18n.t("plugins.subscription_management.subscribe_requires_arguments")) expect(subscription).to be_blank teardown_list_and_mailer(list) end it "x-unsubscribe without argument" do list = create(:list) list.subscribe("schleuder@example.org", '59C71FB38AEE22E091C78259D06350440F759BD3', true) list.import_key(File.read('spec/fixtures/example_key.txt')) list.subscribe("admin@example.org", 'C4D60F8833789C7CAA44496FD3FFA6613AB10ECE', true) ENV['GNUPGHOME'] = list.listdir mail = Mail.new mail.to = list.request_address mail.from = 'schleuder@example.org' gpg_opts = { encrypt: true, keys: {list.request_address => list.fingerprint}, sign: true, sign_as: '59C71FB38AEE22E091C78259D06350440F759BD3' } mail.gpg(gpg_opts) mail.body = "x-list-name: #{list.email}\nX-UNSUBSCRIBE:" mail.deliver encrypted_mail = Mail::TestMailer.deliveries.first Mail::TestMailer.deliveries.clear begin Schleuder::Runner.new().run(encrypted_mail.to_s, list.request_address) rescue SystemExit end raw = Mail::TestMailer.deliveries.first message = Mail.create_message_to_list(raw.to_s, list.request_address, list).setup subscription = list.subscriptions.where(email: 'test@example.org').first expect(message.to).to eql(['schleuder@example.org']) expect(message.to_s).to include("schleuder@example.org has been unsubscribed") expect(subscription).to be_blank teardown_list_and_mailer(list) end it "x-unsubscribe with invalid argument" do list = create(:list) list.subscribe("schleuder@example.org", '59C71FB38AEE22E091C78259D06350440F759BD3', true) ENV['GNUPGHOME'] = list.listdir mail = Mail.new mail.to = list.request_address mail.from = list.admins.first.email gpg_opts = { encrypt: true, keys: {list.request_address => list.fingerprint}, sign: true, sign_as: list.admins.first.fingerprint } mail.gpg(gpg_opts) mail.body = "x-list-name: #{list.email}\nX-UNSUBSCRIBE: test@example.org" mail.deliver encrypted_mail = Mail::TestMailer.deliveries.first Mail::TestMailer.deliveries.clear begin Schleuder::Runner.new().run(encrypted_mail.to_s, list.request_address) rescue SystemExit end raw = Mail::TestMailer.deliveries.first message = Mail.create_message_to_list(raw.to_s, list.request_address, list).setup expect(message.to).to eql(['schleuder@example.org']) expect(message.to_s).to include("test@example.org is not subscribed") teardown_list_and_mailer(list) end it "x-unsubscribe" do list = create(:list) list.subscribe("schleuder@example.org", '59C71FB38AEE22E091C78259D06350440F759BD3', true) list.subscribe("test@example.org") ENV['GNUPGHOME'] = list.listdir mail = Mail.new mail.to = list.request_address mail.from = list.admins.first.email gpg_opts = { encrypt: true, keys: {list.request_address => list.fingerprint}, sign: true, sign_as: list.admins.first.fingerprint } mail.gpg(gpg_opts) mail.body = "x-list-name: #{list.email}\nX-UNSUBSCRIBE: test@example.org" mail.deliver encrypted_mail = Mail::TestMailer.deliveries.first Mail::TestMailer.deliveries.clear begin Schleuder::Runner.new().run(encrypted_mail.to_s, list.request_address) rescue SystemExit end raw = Mail::TestMailer.deliveries.first message = Mail.create_message_to_list(raw.to_s, list.request_address, list).setup subscription = list.subscriptions.where(email: 'test@example.org').first expect(message.to).to eql(['schleuder@example.org']) expect(message.to_s).to include("test@example.org has been unsubscribed") expect(subscription).to be_blank teardown_list_and_mailer(list) end it "x-unsubscribe doesn't unsubscribe last admin" do list = create(:list) list.subscribe("schleuder@example.org", '59C71FB38AEE22E091C78259D06350440F759BD3', true) list.subscribe("test@example.org") ENV['GNUPGHOME'] = list.listdir mail = Mail.new mail.to = list.request_address mail.from = list.admins.first.email gpg_opts = { encrypt: true, keys: {list.request_address => list.fingerprint}, sign: true, sign_as: list.admins.first.fingerprint } mail.gpg(gpg_opts) mail.body = "x-list-name: #{list.email}\nX-UNSUBSCRIBE: schleuder@example.org" mail.deliver encrypted_mail = Mail::TestMailer.deliveries.first Mail::TestMailer.deliveries.clear begin Schleuder::Runner.new().run(encrypted_mail.to_s, list.request_address) rescue SystemExit end raw = Mail::TestMailer.deliveries.first message = Mail.create_message_to_list(raw.to_s, list.request_address, list).setup expect(message.to).to eql(['schleuder@example.org']) expect(message.first_plaintext_part.body.to_s).to eql(I18n.t('plugins.subscription_management.cannot_unsubscribe_last_admin', email: 'schleuder@example.org')) expect(list.subscriptions.size).to be(2) teardown_list_and_mailer(list) end it "x-set-fingerprint with own email-address and valid fingerprint" do list = create(:list) list.subscribe("schleuder@example.org", '59C71FB38AEE22E091C78259D06350440F759BD3', true) list.import_key(File.read('spec/fixtures/example_key.txt')) ENV['GNUPGHOME'] = list.listdir mail = Mail.new mail.to = list.request_address mail.from = list.admins.first.email gpg_opts = { encrypt: true, keys: {list.request_address => list.fingerprint}, sign: true, sign_as: list.admins.first.fingerprint } mail.gpg(gpg_opts) mail.body = "x-list-name: #{list.email}\nX-set-fingerprint: schleuder@example.org C4D60F8833789C7CAA44496FD3FFA6613AB10ECE" mail.deliver encrypted_mail = Mail::TestMailer.deliveries.first Mail::TestMailer.deliveries.clear begin Schleuder::Runner.new().run(encrypted_mail.to_s, list.request_address) rescue SystemExit end raw = Mail::TestMailer.deliveries.first message = Mail.create_message_to_list(raw.to_s, list.request_address, list).setup subscription = list.subscriptions.where(email: 'schleuder@example.org').first expect(message.to).to eql(['schleuder@example.org']) expect(message.to_s).to include("Fingerprint for schleuder@example.org set to C4D60F8833789C7CAA44496FD3FFA6613AB10ECE") expect(subscription).to be_present expect(subscription.fingerprint).to eql('C4D60F8833789C7CAA44496FD3FFA6613AB10ECE') teardown_list_and_mailer(list) end it "x-set-fingerprint with own email-address and valid, spaces-separated fingerprint" do list = create(:list) list.subscribe("schleuder@example.org", '59C71FB38AEE22E091C78259D06350440F759BD3', true) list.import_key(File.read('spec/fixtures/example_key.txt')) ENV['GNUPGHOME'] = list.listdir mail = Mail.new mail.to = list.request_address mail.from = list.admins.first.email gpg_opts = { encrypt: true, keys: {list.request_address => list.fingerprint}, sign: true, sign_as: list.admins.first.fingerprint } mail.gpg(gpg_opts) mail.body = "x-list-name: #{list.email}\nX-set-fingerprint: schleuder@example.org C4D6 0F88 3378 9C7C AA44 496F D3FF A661 3AB1 0ECE" mail.deliver encrypted_mail = Mail::TestMailer.deliveries.first Mail::TestMailer.deliveries.clear begin Schleuder::Runner.new().run(encrypted_mail.to_s, list.request_address) rescue SystemExit end raw = Mail::TestMailer.deliveries.first message = Mail.create_message_to_list(raw.to_s, list.request_address, list).setup subscription = list.subscriptions.where(email: 'schleuder@example.org').first expect(message.to).to eql(['schleuder@example.org']) expect(message.to_s).to include("Fingerprint for schleuder@example.org set to C4D60F8833789C7CAA44496FD3FFA6613AB10ECE") expect(subscription).to be_present expect(subscription.fingerprint).to eql('C4D60F8833789C7CAA44496FD3FFA6613AB10ECE') teardown_list_and_mailer(list) end it "x-set-fingerprint without email-address and with valid fingerprint" do list = create(:list) list.subscribe("schleuder@example.org", '59C71FB38AEE22E091C78259D06350440F759BD3', true) list.import_key(File.read('spec/fixtures/example_key.txt')) ENV['GNUPGHOME'] = list.listdir mail = Mail.new mail.to = list.request_address mail.from = list.admins.first.email gpg_opts = { encrypt: true, keys: {list.request_address => list.fingerprint}, sign: true, sign_as: list.admins.first.fingerprint } mail.gpg(gpg_opts) mail.body = "x-list-name: #{list.email}\nX-set-fingerprint: C4D60F8833789C7CAA44496FD3FFA6613AB10ECE" mail.deliver encrypted_mail = Mail::TestMailer.deliveries.first Mail::TestMailer.deliveries.clear begin Schleuder::Runner.new().run(encrypted_mail.to_s, list.request_address) rescue SystemExit end raw = Mail::TestMailer.deliveries.first message = Mail.create_message_to_list(raw.to_s, list.request_address, list).setup subscription = list.subscriptions.where(email: 'schleuder@example.org').first expect(message.to).to eql(['schleuder@example.org']) expect(message.to_s).to include("Fingerprint for schleuder@example.org set to C4D60F8833789C7CAA44496FD3FFA6613AB10ECE") expect(subscription).to be_present expect(subscription.fingerprint).to eql('C4D60F8833789C7CAA44496FD3FFA6613AB10ECE') teardown_list_and_mailer(list) end it "x-set-fingerprint with other email-address and valid fingerprint" do list = create(:list) list.subscribe("schleuder@example.org", '59C71FB38AEE22E091C78259D06350440F759BD3', true) list.subscribe('test@example.org') list.import_key(File.read('spec/fixtures/example_key.txt')) ENV['GNUPGHOME'] = list.listdir mail = Mail.new mail.to = list.request_address mail.from = list.admins.first.email gpg_opts = { encrypt: true, keys: {list.request_address => list.fingerprint}, sign: true, sign_as: list.admins.first.fingerprint } mail.gpg(gpg_opts) mail.body = "x-list-name: #{list.email}\nX-set-fingerprint: test@example.org C4D60F8833789C7CAA44496FD3FFA6613AB10ECE" mail.deliver encrypted_mail = Mail::TestMailer.deliveries.first Mail::TestMailer.deliveries.clear begin Schleuder::Runner.new().run(encrypted_mail.to_s, list.request_address) rescue SystemExit end raw = Mail::TestMailer.deliveries.first message = Mail.create_message_to_list(raw.to_s, list.request_address, list).setup subscription = list.subscriptions.where(email: 'test@example.org').first expect(message.to).to eql(['schleuder@example.org']) expect(message.to_s).to include("Fingerprint for test@example.org set to C4D60F8833789C7CAA44496FD3FFA6613AB10ECE") expect(subscription).to be_present expect(subscription.fingerprint).to eql('C4D60F8833789C7CAA44496FD3FFA6613AB10ECE') teardown_list_and_mailer(list) end it "x-set-fingerprint with other email-address and valid fingerprint as non-admin" do list = create(:list) list.subscribe("schleuder@example.org", '59C71FB38AEE22E091C78259D06350440F759BD3') list.subscribe("test@example.org", 'C4D60F8833789C7CAA44496FD3FFA6613AB10ECE', true) list.import_key(File.read('spec/fixtures/example_key.txt')) ENV['GNUPGHOME'] = list.listdir mail = Mail.new mail.to = list.request_address mail.from = 'schleuder@example.org' gpg_opts = { encrypt: true, keys: {list.request_address => list.fingerprint}, sign: true, sign_as: '59C71FB38AEE22E091C78259D06350440F759BD3' } mail.gpg(gpg_opts) mail.body = "x-list-name: #{list.email}\nX-set-fingerprint: test@example.org 59C71FB38AEE22E091C78259D06350440F759BD3" mail.deliver encrypted_mail = Mail::TestMailer.deliveries.first Mail::TestMailer.deliveries.clear begin Schleuder::Runner.new().run(encrypted_mail.to_s, list.request_address) rescue SystemExit end raw = Mail::TestMailer.deliveries.first message = Mail.create_message_to_list(raw.to_s, list.request_address, list).setup subscription = list.subscriptions.where(email: 'test@example.org').first expect(message.to).to eql(['schleuder@example.org']) expect(message.to_s).to include("Only admins may set fingerprints of subscriptions other than their own") expect(subscription).to be_present expect(subscription.fingerprint).to eql('C4D60F8833789C7CAA44496FD3FFA6613AB10ECE') teardown_list_and_mailer(list) end it "x-set-fingerprint with email-address but without fingerprint" do list = create(:list) list.subscribe("schleuder@example.org", '59C71FB38AEE22E091C78259D06350440F759BD3', true) list.import_key(File.read('spec/fixtures/example_key.txt')) ENV['GNUPGHOME'] = list.listdir mail = Mail.new mail.to = list.request_address mail.from = list.admins.first.email gpg_opts = { encrypt: true, keys: {list.request_address => list.fingerprint}, sign: true, sign_as: list.admins.first.fingerprint } mail.gpg(gpg_opts) mail.body = "x-list-name: #{list.email}\nX-set-fingerprint: schleuder@example.org " mail.deliver encrypted_mail = Mail::TestMailer.deliveries.first Mail::TestMailer.deliveries.clear begin Schleuder::Runner.new().run(encrypted_mail.to_s, list.request_address) rescue SystemExit end raw = Mail::TestMailer.deliveries.first message = Mail.create_message_to_list(raw.to_s, list.request_address, list).setup subscription = list.subscriptions.where(email: 'schleuder@example.org').first expect(message.to).to eql(['schleuder@example.org']) expect(message.first_plaintext_part.body.to_s).to eql(I18n.t( "plugins.subscription_management.set_fingerprint_requires_valid_fingerprint", fingerprint: '' )) expect(subscription).to be_present expect(subscription.fingerprint).to eql('59C71FB38AEE22E091C78259D06350440F759BD3') teardown_list_and_mailer(list) end it "x-set-fingerprint with email-address but without valid fingerprint" do list = create(:list) list.subscribe("schleuder@example.org", '59C71FB38AEE22E091C78259D06350440F759BD3', true) list.import_key(File.read('spec/fixtures/example_key.txt')) ENV['GNUPGHOME'] = list.listdir mail = Mail.new mail.to = list.request_address mail.from = list.admins.first.email gpg_opts = { encrypt: true, keys: {list.request_address => list.fingerprint}, sign: true, sign_as: list.admins.first.fingerprint } mail.gpg(gpg_opts) mail.body = "x-list-name: #{list.email}\nX-set-fingerprint: schleuder@example.org 59C71FB38AEE22E091C78259D0" mail.deliver encrypted_mail = Mail::TestMailer.deliveries.first Mail::TestMailer.deliveries.clear begin Schleuder::Runner.new().run(encrypted_mail.to_s, list.request_address) rescue SystemExit end raw = Mail::TestMailer.deliveries.first message = Mail.create_message_to_list(raw.to_s, list.request_address, list).setup subscription = list.subscriptions.where(email: 'schleuder@example.org').first expect(message.to).to eql(['schleuder@example.org']) # arguments are downcased when parsed expect(message.first_plaintext_part.body.to_s).to eql(I18n.t( "plugins.subscription_management.set_fingerprint_requires_valid_fingerprint", fingerprint: '59C71FB38AEE22E091C78259D0'.downcase )) expect(subscription).to be_present expect(subscription.fingerprint).to eql('59C71FB38AEE22E091C78259D06350440F759BD3') teardown_list_and_mailer(list) end it "x-set-fingerprint without email-address and with invalid fingerprint" do list = create(:list) list.subscribe("schleuder@example.org", '59C71FB38AEE22E091C78259D06350440F759BD3', true) ENV['GNUPGHOME'] = list.listdir mail = Mail.new mail.to = list.request_address mail.from = list.admins.first.email gpg_opts = { encrypt: true, keys: {list.request_address => list.fingerprint}, sign: true, sign_as: list.admins.first.fingerprint } mail.gpg(gpg_opts) mail.body = "x-list-name: #{list.email}\nX-set-fingerprint: blaBLA" mail.deliver encrypted_mail = Mail::TestMailer.deliveries.first Mail::TestMailer.deliveries.clear begin Schleuder::Runner.new().run(encrypted_mail.to_s, list.request_address) rescue SystemExit end raw = Mail::TestMailer.deliveries.first message = Mail.create_message_to_list(raw.to_s, list.request_address, list).setup subscription = list.subscriptions.where(email: 'schleuder@example.org').first expect(message.to).to eql(['schleuder@example.org']) # arguments are downcased when parsed expect(message.first_plaintext_part.body.to_s).to eql(I18n.t( "plugins.subscription_management.set_fingerprint_requires_valid_fingerprint", fingerprint: 'blaBLA'.downcase )) expect(subscription.fingerprint).to eql('59C71FB38AEE22E091C78259D06350440F759BD3') teardown_list_and_mailer(list) end it "x-set-fingerprint with not-subscribed email-address and valid fingerprint" do list = create(:list) list.subscribe("schleuder@example.org", '59C71FB38AEE22E091C78259D06350440F759BD3', true) ENV['GNUPGHOME'] = list.listdir mail = Mail.new mail.to = list.request_address mail.from = list.admins.first.email gpg_opts = { encrypt: true, keys: {list.request_address => list.fingerprint}, sign: true, sign_as: list.admins.first.fingerprint } mail.gpg(gpg_opts) mail.body = "x-list-name: #{list.email}\nX-set-fingerprint: bla@example.org C4D60F8833789C7CAA44496FD3FFA6613AB10ECE" mail.deliver encrypted_mail = Mail::TestMailer.deliveries.first Mail::TestMailer.deliveries.clear begin Schleuder::Runner.new().run(encrypted_mail.to_s, list.request_address) rescue SystemExit end raw = Mail::TestMailer.deliveries.first message = Mail.create_message_to_list(raw.to_s, list.request_address, list).setup expect(message.to).to eql(['schleuder@example.org']) expect(message.to_s).to include("bla@example.org is not subscribed") teardown_list_and_mailer(list) end it "x-set-fingerprint without argument" do list = create(:list) list.subscribe("schleuder@example.org", '59C71FB38AEE22E091C78259D06350440F759BD3', true) ENV['GNUPGHOME'] = list.listdir mail = Mail.new mail.to = list.request_address mail.from = list.admins.first.email gpg_opts = { encrypt: true, keys: {list.request_address => list.fingerprint}, sign: true, sign_as: list.admins.first.fingerprint } mail.gpg(gpg_opts) mail.body = "x-list-name: #{list.email}\nX-set-fingerprint: " mail.deliver encrypted_mail = Mail::TestMailer.deliveries.first Mail::TestMailer.deliveries.clear begin Schleuder::Runner.new().run(encrypted_mail.to_s, list.request_address) rescue SystemExit end raw = Mail::TestMailer.deliveries.first message = Mail.create_message_to_list(raw.to_s, list.request_address, list).setup expect(message.to).to eql(['schleuder@example.org']) expect(message.first_plaintext_part.body.to_s).to eql(I18n.t("plugins.subscription_management.set_fingerprint_requires_arguments")) teardown_list_and_mailer(list) end it "x-unset-fingerprint without argument" do list = create(:list) list.subscribe("schleuder@example.org", '59C71FB38AEE22E091C78259D06350440F759BD3', true) ENV['GNUPGHOME'] = list.listdir mail = Mail.new mail.to = list.request_address mail.from = list.admins.first.email gpg_opts = { encrypt: true, keys: {list.request_address => list.fingerprint}, sign: true, sign_as: list.admins.first.fingerprint } mail.gpg(gpg_opts) mail.body = "x-list-name: #{list.email}\nX-unset-fingerprint: " mail.deliver encrypted_mail = Mail::TestMailer.deliveries.first Mail::TestMailer.deliveries.clear begin Schleuder::Runner.new().run(encrypted_mail.to_s, list.request_address) rescue SystemExit end raw = Mail::TestMailer.deliveries.first message = Mail.create_message_to_list(raw.to_s, list.request_address, list).setup expect(message.to).to eql(['schleuder@example.org']) expect(message.first_plaintext_part.body.to_s).to eql(I18n.t("plugins.subscription_management.unset_fingerprint_requires_arguments")) teardown_list_and_mailer(list) end it "x-unset-fingerprint with other email-address as admin" do list = create(:list) list.subscribe("schleuder@example.org", '59C71FB38AEE22E091C78259D06350440F759BD3', true) list.subscribe('test@example.org','C4D60F8833789C7CAA44496FD3FFA6613AB10ECE') list.import_key(File.read('spec/fixtures/example_key.txt')) ENV['GNUPGHOME'] = list.listdir mail = Mail.new mail.to = list.request_address mail.from = list.admins.first.email gpg_opts = { encrypt: true, keys: {list.request_address => list.fingerprint}, sign: true, sign_as: list.admins.first.fingerprint } mail.gpg(gpg_opts) mail.body = "x-list-name: #{list.email}\nX-unset-fingerprint: test@example.org" mail.deliver encrypted_mail = Mail::TestMailer.deliveries.first Mail::TestMailer.deliveries.clear begin Schleuder::Runner.new().run(encrypted_mail.to_s, list.request_address) rescue SystemExit end raw = Mail::TestMailer.deliveries.first message = Mail.create_message_to_list(raw.to_s, list.request_address, list).setup subscription = list.subscriptions.where(email: 'test@example.org').first expect(message.to).to eql(['schleuder@example.org']) expect(message.to_s).to include("Fingerprint for test@example.org removed.") expect(subscription).to be_present expect(subscription.fingerprint.blank?).to be_truthy teardown_list_and_mailer(list) end it "x-unset-fingerprint with own email-address as admin but without force" do list = create(:list) list.subscribe("schleuder@example.org", '59C71FB38AEE22E091C78259D06350440F759BD3', true) list.import_key(File.read('spec/fixtures/example_key.txt')) ENV['GNUPGHOME'] = list.listdir mail = Mail.new mail.to = list.request_address mail.from = list.admins.first.email gpg_opts = { encrypt: true, keys: {list.request_address => list.fingerprint}, sign: true, sign_as: list.admins.first.fingerprint } mail.gpg(gpg_opts) mail.body = "x-list-name: #{list.email}\nX-unset-fingerprint: schleuder@example.org" mail.deliver encrypted_mail = Mail::TestMailer.deliveries.first Mail::TestMailer.deliveries.clear begin Schleuder::Runner.new().run(encrypted_mail.to_s, list.request_address) rescue SystemExit end raw = Mail::TestMailer.deliveries.first message = Mail.create_message_to_list(raw.to_s, list.request_address, list).setup subscription = list.subscriptions.where(email: 'schleuder@example.org').first expect(message.to).to eql(['schleuder@example.org']) expect(message.first_plaintext_part.body.to_s).to eql(I18n.t("plugins.subscription_management.unset_fingerprint_requires_arguments")) expect(subscription).to be_present expect(subscription.fingerprint).to eql('59C71FB38AEE22E091C78259D06350440F759BD3') teardown_list_and_mailer(list) end it "x-unset-fingerprint with own email-address as admin and force" do list = create(:list) list.subscribe("schleuder@example.org", '59C71FB38AEE22E091C78259D06350440F759BD3', true) list.import_key(File.read('spec/fixtures/example_key.txt')) ENV['GNUPGHOME'] = list.listdir mail = Mail.new mail.to = list.request_address mail.from = list.admins.first.email gpg_opts = { encrypt: true, keys: {list.request_address => list.fingerprint}, sign: true, sign_as: list.admins.first.fingerprint } mail.gpg(gpg_opts) mail.body = "x-list-name: #{list.email}\nX-unset-fingerprint: schleuder@example.org force" mail.deliver encrypted_mail = Mail::TestMailer.deliveries.first Mail::TestMailer.deliveries.clear begin Schleuder::Runner.new().run(encrypted_mail.to_s, list.request_address) rescue SystemExit end raw = Mail::TestMailer.deliveries.first message = Mail.create_message_to_list(raw.to_s, list.request_address, list).setup subscription = list.subscriptions.where(email: 'schleuder@example.org').first expect(message.to).to eql(['schleuder@example.org']) expect(message.to_s).to include("Fingerprint for schleuder@example.org removed.") expect(subscription).to be_present expect(subscription.fingerprint.blank?).to be_truthy teardown_list_and_mailer(list) end it "x-unset-fingerprint with not-subscribed email-address" do list = create(:list) list.subscribe("schleuder@example.org", '59C71FB38AEE22E091C78259D06350440F759BD3', true) ENV['GNUPGHOME'] = list.listdir mail = Mail.new mail.to = list.request_address mail.from = list.admins.first.email gpg_opts = { encrypt: true, keys: {list.request_address => list.fingerprint}, sign: true, sign_as: list.admins.first.fingerprint } mail.gpg(gpg_opts) mail.body = "x-list-name: #{list.email}\nX-unset-fingerprint: bla@example.org" mail.deliver encrypted_mail = Mail::TestMailer.deliveries.first Mail::TestMailer.deliveries.clear begin Schleuder::Runner.new().run(encrypted_mail.to_s, list.request_address) rescue SystemExit end raw = Mail::TestMailer.deliveries.first message = Mail.create_message_to_list(raw.to_s, list.request_address, list).setup expect(message.to).to eql(['schleuder@example.org']) expect(message.to_s).to include("bla@example.org is not subscribed") teardown_list_and_mailer(list) end it "x-unset-fingerprint with other email-address as non-admin" do list = create(:list) list.subscribe("schleuder@example.org", '59C71FB38AEE22E091C78259D06350440F759BD3') list.subscribe("test@example.org", 'C4D60F8833789C7CAA44496FD3FFA6613AB10ECE', true) list.import_key(File.read('spec/fixtures/example_key.txt')) ENV['GNUPGHOME'] = list.listdir mail = Mail.new mail.to = list.request_address mail.from = 'schleuder@example.org' gpg_opts = { encrypt: true, keys: {list.request_address => list.fingerprint}, sign: true, sign_as: '59C71FB38AEE22E091C78259D06350440F759BD3' } mail.gpg(gpg_opts) mail.body = "x-list-name: #{list.email}\nX-unset-fingerprint: test@example.org" mail.deliver encrypted_mail = Mail::TestMailer.deliveries.first Mail::TestMailer.deliveries.clear begin Schleuder::Runner.new().run(encrypted_mail.to_s, list.request_address) rescue SystemExit end raw = Mail::TestMailer.deliveries.first message = Mail.create_message_to_list(raw.to_s, list.request_address, list).setup subscription = list.subscriptions.where(email: 'test@example.org').first expect(message.to).to eql(['schleuder@example.org']) expect(message.to_s).to include("Only admins may remove fingerprints of subscriptions other than their own") expect(subscription).to be_present expect(subscription.fingerprint).to eql('C4D60F8833789C7CAA44496FD3FFA6613AB10ECE') teardown_list_and_mailer(list) end it "x-list-subscriptions without arguments" do list = create(:list) list.subscribe("schleuder@example.org", '59C71FB38AEE22E091C78259D06350440F759BD3', true) ENV['GNUPGHOME'] = list.listdir mail = Mail.new mail.to = list.request_address mail.from = list.admins.first.email gpg_opts = { encrypt: true, keys: {list.request_address => list.fingerprint}, sign: true, sign_as: list.admins.first.fingerprint } mail.gpg(gpg_opts) mail.body = "x-list-name: #{list.email}\nX-list-subscriptions:" mail.deliver encrypted_mail = Mail::TestMailer.deliveries.first Mail::TestMailer.deliveries.clear begin Schleuder::Runner.new().run(encrypted_mail.to_s, list.request_address) rescue SystemExit end raw = Mail::TestMailer.deliveries.first message = Mail.create_message_to_list(raw.to_s, list.request_address, list).setup expect(message.to).to eql(['schleuder@example.org']) expect(message.first_plaintext_part.body.to_s.lines.size).to eql(3) expect(message.to_s).to include("schleuder@example.org 0x59C71FB38AEE22E091C78259D06350440F759BD3") teardown_list_and_mailer(list) end it "x-list-subscriptions without arguments but with admin-notification" do list = create(:list, keywords_admin_notify: ['list-subscriptions']) list.subscribe("schleuder@example.org", '59C71FB38AEE22E091C78259D06350440F759BD3', true) list.subscribe("user@example.org") ENV['GNUPGHOME'] = list.listdir mail = Mail.new mail.to = list.request_address mail.from = list.admins.first.email gpg_opts = { encrypt: true, keys: {list.request_address => list.fingerprint}, sign: true, sign_as: list.admins.first.fingerprint } mail.gpg(gpg_opts) mail.body = "x-list-name: #{list.email}\nX-list-subscriptions:" mail.deliver encrypted_mail = Mail::TestMailer.deliveries.first Mail::TestMailer.deliveries.clear begin Schleuder::Runner.new().run(encrypted_mail.to_s, list.request_address) rescue SystemExit end raw = Mail::TestMailer.deliveries.first notification = Mail.create_message_to_list(raw.to_s, list.request_address, list).setup raw = Mail::TestMailer.deliveries[1] response = Mail.create_message_to_list(raw.to_s, list.request_address, list).setup expected_text = "Subscriptions:\n\nschleuder@example.org\t0x59C71FB38AEE22E091C78259D06350440F759BD3\nuser@example.org" expect(Mail::TestMailer.deliveries.size).to eql(2) expect(notification.to).to eql(['schleuder@example.org']) expect(notification.first_plaintext_part.body.to_s).to eql("schleuder@example.org sent the keyword 'list-subscriptions' and received this response:\n\n#{expected_text}") expect(response.to).to eql(['schleuder@example.org']) expect(response.first_plaintext_part.body.to_s).to eql(expected_text) teardown_list_and_mailer(list) end it "x-list-subscriptions with matching argument" do list = create(:list) list.subscribe("schleuder@example.org", '59C71FB38AEE22E091C78259D06350440F759BD3', true) ENV['GNUPGHOME'] = list.listdir mail = Mail.new mail.to = list.request_address mail.from = list.admins.first.email gpg_opts = { encrypt: true, keys: {list.request_address => list.fingerprint}, sign: true, sign_as: list.admins.first.fingerprint } mail.gpg(gpg_opts) mail.body = "x-list-name: #{list.email}\nX-list-subscriptions: example.org" mail.deliver encrypted_mail = Mail::TestMailer.deliveries.first Mail::TestMailer.deliveries.clear begin Schleuder::Runner.new().run(encrypted_mail.to_s, list.request_address) rescue SystemExit end raw = Mail::TestMailer.deliveries.first message = Mail.create_message_to_list(raw.to_s, list.request_address, list).setup expect(message.to).to eql(['schleuder@example.org']) expect(message.first_plaintext_part.body.to_s.lines.size).to eql(3) expect(message.to_s).to include("schleuder@example.org 0x59C71FB38AEE22E091C78259D06350440F759BD3") teardown_list_and_mailer(list) end it "x-list-subscriptions with non-matching argument" do list = create(:list) list.subscribe("schleuder@example.org", '59C71FB38AEE22E091C78259D06350440F759BD3', true) ENV['GNUPGHOME'] = list.listdir mail = Mail.new mail.to = list.request_address mail.from = list.admins.first.email gpg_opts = { encrypt: true, keys: {list.request_address => list.fingerprint}, sign: true, sign_as: list.admins.first.fingerprint } mail.gpg(gpg_opts) mail.body = "x-list-name: #{list.email}\nX-list-subscriptions: blabla" mail.deliver encrypted_mail = Mail::TestMailer.deliveries.first Mail::TestMailer.deliveries.clear begin Schleuder::Runner.new().run(encrypted_mail.to_s, list.request_address) rescue SystemExit end raw = Mail::TestMailer.deliveries.first message = Mail.create_message_to_list(raw.to_s, list.request_address, list).setup expect(message.to).to eql(['schleuder@example.org']) expect(message.first_plaintext_part.body.to_s.lines.size).to eql(1) expect(message.to_s).to include("Your message resulted in no output") teardown_list_and_mailer(list) end it "x-add-key with inline key-material" do list = create(:list, keywords_admin_notify: []) list.subscribe("schleuder@example.org", '59C71FB38AEE22E091C78259D06350440F759BD3', true) list_keys_num = list.keys.size ENV['GNUPGHOME'] = list.listdir mail = Mail.new mail.to = list.request_address mail.from = list.admins.first.email gpg_opts = { encrypt: true, keys: {list.request_address => list.fingerprint}, sign: true, sign_as: list.admins.first.fingerprint } mail.gpg(gpg_opts) keymaterial = File.read('spec/fixtures/example_key.txt') mail.body = "x-list-name: #{list.email}\nX-ADD-KEY:\n#{keymaterial}" mail.deliver encrypted_mail = Mail::TestMailer.deliveries.first Mail::TestMailer.deliveries.clear begin Schleuder::Runner.new().run(encrypted_mail.to_s, list.request_address) rescue SystemExit end raw = Mail::TestMailer.deliveries.first message = Mail.create_message_to_list(raw.to_s, list.request_address, list).setup expect(list.keys.size).to eql(list_keys_num + 1) expect(message.to).to eql(['schleuder@example.org']) expect(message.first_plaintext_part.body.to_s).to match(/^This key was newly added:\n0xC4D60F8833789C7CAA44496FD3FFA6613AB10ECE schleuder2@example.org \d{4}-\d{2}-\d{2}\n$/) teardown_list_and_mailer(list) end it "x-add-key with an inline mix of key and non-key material" do list = create(:list, keywords_admin_notify: []) list.subscribe("schleuder@example.org", '59C71FB38AEE22E091C78259D06350440F759BD3', true) list_keys_num = list.keys.size ENV['GNUPGHOME'] = list.listdir mail = Mail.new mail.to = list.request_address mail.from = list.admins.first.email gpg_opts = { encrypt: true, keys: {list.request_address => list.fingerprint}, sign: true, sign_as: list.admins.first.fingerprint } mail.gpg(gpg_opts) keymaterial1 = File.read('spec/fixtures/example_key.txt') keymaterial2 = File.read('spec/fixtures/bla_foo_key.txt') mail.body = "x-list-name: #{list.email}\nX-ADD-KEY:\n#{keymaterial1}\nsome text\n#{keymaterial2}\n--\nthis is a signature" mail.deliver encrypted_mail = Mail::TestMailer.deliveries.first Mail::TestMailer.deliveries.clear begin Schleuder::Runner.new().run(encrypted_mail.to_s, list.request_address) rescue SystemExit end raw = Mail::TestMailer.deliveries.first message = Mail.create_message_to_list(raw.to_s, list.request_address, list).setup expect(list.keys.size).to eql(list_keys_num + 2) expect(message.to).to eql(['schleuder@example.org']) expect(message.first_plaintext_part.body.to_s).to match(/^This key was newly added:\n0xC4D60F8833789C7CAA44496FD3FFA6613AB10ECE schleuder2@example.org \d{4}-\d{2}-\d{2}\n\n\nThis key was newly added:\n0x87E65ED2081AE3D16BE4F0A5EBDBE899251F2412 bla@foo \d{4}-\d{2}-\d{2}$/) teardown_list_and_mailer(list) end it "x-add-key with attached key-material" do list = create(:list, keywords_admin_notify: []) list.subscribe("schleuder@example.org", '59C71FB38AEE22E091C78259D06350440F759BD3', true) list_keys_num = list.keys.size ENV['GNUPGHOME'] = list.listdir mail = Mail.new mail.to = list.request_address mail.from = list.admins.first.email gpg_opts = { encrypt: true, keys: {list.request_address => list.fingerprint}, sign: true, sign_as: list.admins.first.fingerprint } mail.gpg(gpg_opts) mail.body = "x-list-name: #{list.email}\nX-ADD-KEY:" mail.add_file('spec/fixtures/example_key.txt') mail.deliver encrypted_mail = Mail::TestMailer.deliveries.first Mail::TestMailer.deliveries.clear begin Schleuder::Runner.new().run(encrypted_mail.to_s, list.request_address) rescue SystemExit end raw = Mail::TestMailer.deliveries.first message = Mail.create_message_to_list(raw.to_s, list.request_address, list).setup expect(list.keys.size).to eql(list_keys_num + 1) expect(message.to).to eql(['schleuder@example.org']) expect(message.first_plaintext_part.body.to_s).to match(/^This key was newly added:\n0xC4D60F8833789C7CAA44496FD3FFA6613AB10ECE schleuder2@example.org \d{4}-\d{2}-\d{2}\n$/) teardown_list_and_mailer(list) end it "x-add-key with attached quoted-printable key-material (as produced by Thunderbird)" do list = create(:list, keywords_admin_notify: []) list.subscribe("schleuder@example.org", '59C71FB38AEE22E091C78259D06350440F759BD3', true) list_keys_num = list.keys.size ENV['GNUPGHOME'] = list.listdir mail = Mail.new mail.to = list.request_address mail.from = list.admins.first.email gpg_opts = { encrypt: true, keys: {list.request_address => list.fingerprint}, sign: true, sign_as: list.admins.first.fingerprint } mail.gpg(gpg_opts) keywords = Mail::Part.new keywords.body = "\n\nx-list-name: #{list.email}\nX-ADD-KEY:" mail.parts << keywords mail.attachments['example_key.txt'] = { :content_type => '"application/pgp-keys"; name="example_key.txt"', :content_transfer_encoding => 'quoted-printable', :content => File.read('spec/fixtures/example_key.txt') } mail.deliver encrypted_mail = Mail::TestMailer.deliveries.first Mail::TestMailer.deliveries.clear begin Schleuder::Runner.new().run(encrypted_mail.to_s, list.request_address) rescue SystemExit end raw = Mail::TestMailer.deliveries.first message = Mail.create_message_to_list(raw.to_s, list.request_address, list).setup expect(list.keys.size).to eql(list_keys_num + 1) expect(message.to).to eql(['schleuder@example.org']) expect(message.first_plaintext_part.body.to_s).to match(/^This key was newly added:\n0xC4D60F8833789C7CAA44496FD3FFA6613AB10ECE schleuder2@example.org \d{4}-\d{2}-\d{2}\n$/) teardown_list_and_mailer(list) end it "x-add-key to update a key" do list = create(:list, keywords_admin_notify: []) list.subscribe("schleuder@example.org", '59C71FB38AEE22E091C78259D06350440F759BD3', true) list.import_key(File.read("spec/fixtures/expired_key.txt")) list_keys_num = list.keys.size ENV['GNUPGHOME'] = list.listdir mail = Mail.new mail.to = list.request_address mail.from = list.admins.first.email gpg_opts = { encrypt: true, keys: {list.request_address => list.fingerprint}, sign: true, sign_as: list.admins.first.fingerprint } mail.gpg(gpg_opts) mail.body = "x-list-name: #{list.email}\nX-ADD-KEY:" mail.add_file("spec/fixtures/expired_key_extended.txt") mail.deliver encrypted_mail = Mail::TestMailer.deliveries.first Mail::TestMailer.deliveries.clear begin Schleuder::Runner.new().run(encrypted_mail.to_s, list.request_address) rescue SystemExit end raw = Mail::TestMailer.deliveries.first message = Mail.create_message_to_list(raw.to_s, list.request_address, list).setup expect(list.keys.size).to eql(list_keys_num) expect(message.to).to eql(['schleuder@example.org']) expect(message.first_plaintext_part.body.to_s).to match(/^This key was updated:\n0x98769E8A1091F36BD88403ECF71A3F8412D83889 bla@foo \d{4}-\d{2}-\d{2} \[expired: \d{4}-\d{2}-\d{2}\]\n$/) teardown_list_and_mailer(list) end it "x-add-key with garbage as key-material" do list = create(:list, keywords_admin_notify: []) list.subscribe("schleuder@example.org", '59C71FB38AEE22E091C78259D06350440F759BD3', true) list_keys_num = list.keys.size ENV['GNUPGHOME'] = list.listdir mail = Mail.new mail.to = list.request_address mail.from = list.admins.first.email gpg_opts = { encrypt: true, keys: {list.request_address => list.fingerprint}, sign: true, sign_as: list.admins.first.fingerprint } mail.gpg(gpg_opts) mail.body = "x-list-name: #{list.email}\nX-ADD-KEY:\nlakdsjflaksjdflakjsdflkajsdf" mail.deliver encrypted_mail = Mail::TestMailer.deliveries.first Mail::TestMailer.deliveries.clear begin Schleuder::Runner.new().run(encrypted_mail.to_s, list.request_address) rescue SystemExit end raw = Mail::TestMailer.deliveries.first message = Mail.create_message_to_list(raw.to_s, list.request_address, list).setup expect(list.keys.size).to eql(list_keys_num) expect(message.to).to eql(['schleuder@example.org']) expect(message.first_plaintext_part.body.to_s).to eql("In the message you sent us, no keys could be found. :(") teardown_list_and_mailer(list) end it "x-fetch-key with invalid input" do list = create(:list) list.subscribe("schleuder@example.org", '59C71FB38AEE22E091C78259D06350440F759BD3', true) list_keys_num = list.keys.size ENV['GNUPGHOME'] = list.listdir mail = Mail.new mail.to = list.request_address mail.from = list.admins.first.email gpg_opts = { encrypt: true, keys: {list.request_address => list.fingerprint}, sign: true, sign_as: list.admins.first.fingerprint } mail.gpg(gpg_opts) mail.body = "x-list-name: #{list.email}\nX-fetch-KEY: lala!" mail.deliver encrypted_mail = Mail::TestMailer.deliveries.first Mail::TestMailer.deliveries.clear begin Schleuder::Runner.new().run(encrypted_mail.to_s, list.request_address) rescue SystemExit end raw = Mail::TestMailer.deliveries.first message = Mail.create_message_to_list(raw.to_s, list.request_address, list).setup expect(list.keys.size).to eql(list_keys_num) expect(message.to_s).to include("Invalid input.") teardown_list_and_mailer(list) end it "x-fetch-key with email address" do list = create(:list) list.subscribe("schleuder@example.org", '59C71FB38AEE22E091C78259D06350440F759BD3', true) list_keys_num = list.keys.size ENV['GNUPGHOME'] = list.listdir mail = Mail.new mail.to = list.request_address mail.from = list.admins.first.email gpg_opts = { encrypt: true, keys: {list.request_address => list.fingerprint}, sign: true, sign_as: list.admins.first.fingerprint } mail.gpg(gpg_opts) mail.body = "x-list-name: #{list.email}\nX-fetch-KEY: admin@example.org" mail.deliver encrypted_mail = Mail::TestMailer.deliveries.first Mail::TestMailer.deliveries.clear with_sks_mock(list.listdir) do begin Schleuder::Runner.new().run(encrypted_mail.to_s, list.request_address) rescue SystemExit end end raw = Mail::TestMailer.deliveries.find { |message| message.to == [list.admins.first.email] } message = Mail.create_message_to_list(raw.to_s, list.request_address, list).setup expect(list.keys.size).to eql(list_keys_num + 1) expect(message.first_plaintext_part.body.to_s).to match(/This key was fetched \(new key\):\n0x98769E8A1091F36BD88403ECF71A3F8412D83889 bla@foo \d{4}-\d{2}-\d{2} \[expired: \d{4}-\d{2}-\d{2}\]\n/) teardown_list_and_mailer(list) end it "x-fetch-key with unknown email-address" do list = create(:list) list.subscribe("schleuder@example.org", '59C71FB38AEE22E091C78259D06350440F759BD3', true) list_keys_num = list.keys.size ENV['GNUPGHOME'] = list.listdir mail = Mail.new mail.to = list.request_address mail.from = list.admins.first.email gpg_opts = { encrypt: true, keys: {list.request_address => list.fingerprint}, sign: true, sign_as: list.admins.first.fingerprint } mail.gpg(gpg_opts) mail.body = "x-list-name: #{list.email}\nX-fetch-KEY: something@localhost" mail.deliver encrypted_mail = Mail::TestMailer.deliveries.first Mail::TestMailer.deliveries.clear with_sks_mock(list.listdir) do begin Schleuder::Runner.new().run(encrypted_mail.to_s, list.request_address) rescue SystemExit end end raw = Mail::TestMailer.deliveries.find { |message| message.to == [list.admins.first.email] } message = Mail.create_message_to_list(raw.to_s, list.request_address, list).setup expect(list.keys.size).to eql(list_keys_num) expect(message.to_s).to include("Fetching something@localhost did not succeed") teardown_list_and_mailer(list) end it "x-fetch-key with URL" do list = create(:list) list.subscribe("schleuder@example.org", '59C71FB38AEE22E091C78259D06350440F759BD3', true) list_keys_num = list.keys.size ENV['GNUPGHOME'] = list.listdir mail = Mail.new mail.to = list.request_address mail.from = list.admins.first.email gpg_opts = { encrypt: true, keys: {list.request_address => list.fingerprint}, sign: true, sign_as: list.admins.first.fingerprint } mail.gpg(gpg_opts) mail.body = "x-list-name: #{list.email}\nX-fetch-KEY: http://localhost:9999/keys/example.asc" mail.deliver encrypted_mail = Mail::TestMailer.deliveries.first Mail::TestMailer.deliveries.clear with_sks_mock(list.listdir) do begin Schleuder::Runner.new().run(encrypted_mail.to_s, list.request_address) rescue SystemExit end end raw = Mail::TestMailer.deliveries.find { |message| message.to == [list.admins.first.email] } message = Mail.create_message_to_list(raw.to_s, list.request_address, list).setup expect(list.keys.size).to eql(list_keys_num + 1) expect(message.first_plaintext_part.body.to_s).to match(/This key was fetched \(new key\):\n0x98769E8A1091F36BD88403ECF71A3F8412D83889 bla@foo \d{4}-\d{2}-\d{2} \[expired: \d{4}-\d{2}-\d{2}\]\n/) teardown_list_and_mailer(list) end it "x-fetch-key with invalid URL" do list = create(:list) list.subscribe("schleuder@example.org", '59C71FB38AEE22E091C78259D06350440F759BD3', true) list_keys_num = list.keys.size ENV['GNUPGHOME'] = list.listdir mail = Mail.new mail.to = list.request_address mail.from = list.admins.first.email gpg_opts = { encrypt: true, keys: {list.request_address => list.fingerprint}, sign: true, sign_as: list.admins.first.fingerprint } mail.gpg(gpg_opts) url = "http://localhost:9999/foo" mail.body = "x-list-name: #{list.email}\nX-fetch-KEY: #{url}" mail.deliver encrypted_mail = Mail::TestMailer.deliveries.first Mail::TestMailer.deliveries.clear with_sks_mock(list.listdir) do begin Schleuder::Runner.new().run(encrypted_mail.to_s, list.request_address) rescue SystemExit end end raw = Mail::TestMailer.deliveries.find { |message| message.to == [list.admins.first.email] } message = Mail.create_message_to_list(raw.to_s, list.request_address, list).setup expect(list.keys.size).to eql(list_keys_num) expect(message.to_s).to include("Fetching #{url} did not succeed") teardown_list_and_mailer(list) end it "x-fetch-key with unknown fingerprint" do list = create(:list) list.subscribe("schleuder@example.org", '59C71FB38AEE22E091C78259D06350440F759BD3', true) list_keys_num = list.keys.size ENV['GNUPGHOME'] = list.listdir mail = Mail.new mail.to = list.request_address mail.from = list.admins.first.email gpg_opts = { encrypt: true, keys: {list.request_address => list.fingerprint}, sign: true, sign_as: list.admins.first.fingerprint } mail.gpg(gpg_opts) mail.body = "x-list-name: #{list.email}\nX-fetch-KEY: 0x0000000000000000000000000000000000000000" mail.deliver encrypted_mail = Mail::TestMailer.deliveries.first Mail::TestMailer.deliveries.clear with_sks_mock(list.listdir) do begin Schleuder::Runner.new().run(encrypted_mail.to_s, list.request_address) rescue SystemExit end end raw = Mail::TestMailer.deliveries.find { |message| message.to == [list.admins.first.email] } message = Mail.create_message_to_list(raw.to_s, list.request_address, list).setup expect(list.keys.size).to eql(list_keys_num) expect(message.to_s).to include("Fetching 0x0000000000000000000000000000000000000000 did not succeed") teardown_list_and_mailer(list) end it "x-fetch-key with fingerprint" do list = create(:list) list.subscribe("schleuder@example.org", '59C71FB38AEE22E091C78259D06350440F759BD3', true) list_keys_num = list.keys.size ENV['GNUPGHOME'] = list.listdir mail = Mail.new mail.to = list.request_address mail.from = list.admins.first.email gpg_opts = { encrypt: true, keys: {list.request_address => list.fingerprint}, sign: true, sign_as: list.admins.first.fingerprint } mail.gpg(gpg_opts) mail.body = "x-list-name: #{list.email}\nX-fetch-KEY: 0x98769E8A1091F36BD88403ECF71A3F8412D83889" mail.deliver encrypted_mail = Mail::TestMailer.deliveries.first Mail::TestMailer.deliveries.clear with_sks_mock(list.listdir) do begin Schleuder::Runner.new().run(encrypted_mail.to_s, list.request_address) rescue SystemExit end end raw = Mail::TestMailer.deliveries.find { |message| message.to == [list.admins.first.email] } message = Mail.create_message_to_list(raw.to_s, list.request_address, list).setup expect(list.keys.size).to eql(list_keys_num + 1) expect(message.first_plaintext_part.body.to_s).to match(/This key was fetched \(new key\):\n0x98769E8A1091F36BD88403ECF71A3F8412D83889 bla@foo \d{4}-\d{2}-\d{2} \[expired: \d{4}-\d{2}-\d{2}\]\n/) teardown_list_and_mailer(list) end it "x-fetch-key with fingerprint of unchanged key" do list = create(:list) list.subscribe("schleuder@example.org", '59C71FB38AEE22E091C78259D06350440F759BD3', true) list_keys_num = list.keys.size ENV['GNUPGHOME'] = list.listdir mail = Mail.new mail.to = list.request_address mail.from = list.admins.first.email gpg_opts = { encrypt: true, keys: {list.request_address => list.fingerprint}, sign: true, sign_as: list.admins.first.fingerprint } mail.gpg(gpg_opts) mail.body = "x-list-name: #{list.email}\nX-fetch-KEY: 0x59C71FB38AEE22E091C78259D06350440F759BD3" mail.deliver encrypted_mail = Mail::TestMailer.deliveries.first Mail::TestMailer.deliveries.clear with_sks_mock(list.listdir) do begin Schleuder::Runner.new().run(encrypted_mail.to_s, list.request_address) rescue SystemExit end end raw = Mail::TestMailer.deliveries.find { |message| message.to == [list.admins.first.email] } message = Mail.create_message_to_list(raw.to_s, list.request_address, list).setup expect(list.keys.size).to eql(list_keys_num) expect(message.first_plaintext_part.body.to_s).to match(/This key was fetched \(unchanged\):\n0x59C71FB38AEE22E091C78259D06350440F759BD3 schleuder@example.org \d{4}-\d{2}-\d{2}/) teardown_list_and_mailer(list) end it "x-fetch-key without arguments" do list = create(:list) list.subscribe("schleuder@example.org", '59C71FB38AEE22E091C78259D06350440F759BD3', true) list_keys_num = list.keys.size ENV['GNUPGHOME'] = list.listdir mail = Mail.new mail.to = list.request_address mail.from = list.admins.first.email gpg_opts = { encrypt: true, keys: {list.request_address => list.fingerprint}, sign: true, sign_as: list.admins.first.fingerprint } mail.gpg(gpg_opts) mail.body = "x-list-name: #{list.email}\nX-fetch-KEY: " mail.deliver encrypted_mail = Mail::TestMailer.deliveries.first Mail::TestMailer.deliveries.clear with_sks_mock(list.listdir) do begin Schleuder::Runner.new().run(encrypted_mail.to_s, list.request_address) rescue SystemExit end end raw = Mail::TestMailer.deliveries.find { |message| message.to == [list.admins.first.email] } message = Mail.create_message_to_list(raw.to_s, list.request_address, list).setup expect(list.keys.size).to eql(list_keys_num) expect(message.to_s).not_to include("translation missing") expect(message.first_plaintext_part.body.to_s).to eql(I18n.t("plugins.key_management.fetch_key_requires_arguments")) teardown_list_and_mailer(list) end it "x-resend" do list = create(:list, public_footer: "-- \nblablabla") list.subscribe("schleuder@example.org", '59C71FB38AEE22E091C78259D06350440F759BD3', true) ENV['GNUPGHOME'] = list.listdir mail = Mail.new mail.to = list.email mail.from = list.admins.first.email gpg_opts = { encrypt: true, keys: {list.email => list.fingerprint}, sign: true, sign_as: list.admins.first.fingerprint } mail.gpg(gpg_opts) content_body = "Hello again!\n" mail.body = "x-list-name: #{list.email}\nX-resend: someone@example.org\n#{content_body}" mail.deliver encrypted_mail = Mail::TestMailer.deliveries.first Mail::TestMailer.deliveries.clear begin Schleuder::Runner.new().run(encrypted_mail.to_s, list.email) rescue SystemExit end raw = Mail::TestMailer.deliveries.first resent_message = raw.verify resent_message_body = resent_message.parts.map { |p| p.body.to_s }.join raw = Mail::TestMailer.deliveries.last message = Mail.create_message_to_list(raw.to_s, list.email, list).setup expect(message.to).to eql(['schleuder@example.org']) expect(message.to_s).to include("Resent: Unencrypted to someone@example.org") expect(resent_message.to).to include("someone@example.org") expect(resent_message.to_s).not_to include("Resent: Unencrypted to someone@example.org") expect(resent_message_body).to eql(content_body + list.public_footer.to_s) teardown_list_and_mailer(list) end it "does not parse keywords once the mail body started" do list = create(:list, public_footer: "-- \nblablabla") list.subscribe("schleuder@example.org", '59C71FB38AEE22E091C78259D06350440F759BD3', true) ENV['GNUPGHOME'] = list.listdir mail = Mail.new mail.to = list.email mail.from = list.admins.first.email gpg_opts = { encrypt: true, keys: {list.email => list.fingerprint}, sign: true, sign_as: list.admins.first.fingerprint } mail.gpg(gpg_opts) content_body = < list.fingerprint}, sign: true, sign_as: list.admins.first.fingerprint } mail.gpg(gpg_opts) content_body = "Hello again!\n" mail.body = "x-list-name: #{list.email}\nX-resend: someone@example.org\n#{content_body}" mail.deliver encrypted_mail = Mail::TestMailer.deliveries.first Mail::TestMailer.deliveries.clear begin Schleuder::Runner.new().run(encrypted_mail.to_s, list.email) rescue SystemExit end raw = Mail::TestMailer.deliveries.first resent_message = raw.verify resent_message_body = resent_message.parts.map { |p| p.body.to_s }.join expect(resent_message_body).not_to include(list.internal_footer) expect(resent_message_body).to eql(content_body + list.public_footer.to_s) teardown_list_and_mailer(list) end it "x-resend with iso-8859-1 body" do list = create(:list, public_footer: "-- \nblablabla") list.subscribe("schleuder@example.org", '59C71FB38AEE22E091C78259D06350440F759BD3', true) ENV['GNUPGHOME'] = list.listdir mail = Mail.new mail.to = list.email mail.from = list.admins.first.email gpg_opts = { encrypt: true, keys: {list.email => list.fingerprint}, sign: true, sign_as: list.admins.first.fingerprint } mail.gpg(gpg_opts) content_body = "Hello again! ¡Hola!\r\n" mail.charset = 'iso-8859-1' mail.body = "x-list-name: #{list.email}\nX-resend: someone@example.org\n#{content_body}".encode('iso-8859-1') mail.deliver encrypted_mail = Mail::TestMailer.deliveries.first Mail::TestMailer.deliveries.clear begin Schleuder::Runner.new().run(encrypted_mail.to_s, list.email) rescue SystemExit end raw = Mail::TestMailer.deliveries.first resent_message = raw.verify raw = Mail::TestMailer.deliveries.last message = Mail.create_message_to_list(raw.to_s, list.email, list).setup expect(message.to).to eql(['schleuder@example.org']) expect(message.to_s).to include("Resent: Unencrypted to someone@example.org") expect(message.parts[1].body.to_s.force_encoding(message.parts[1].charset)).to eql(content_body.encode(message.parts[1].charset)) expect(resent_message.to).to include("someone@example.org") expect(resent_message.to_s).not_to include("Resent: Unencrypted to someone@example.org") expect(resent_message.parts[0].body.to_s).to eql(content_body.encode(resent_message.parts[0].charset)) expect(resent_message.parts[1].body.to_s).to eql(list.public_footer.to_s) teardown_list_and_mailer(list) end it "x-resend with utf-8 body and umlauts" do list = create(:list) list.subscribe("schleuder@example.org", '59C71FB38AEE22E091C78259D06350440F759BD3', true) ENV['GNUPGHOME'] = list.listdir mail = Mail.new mail.to = list.email mail.from = list.admins.first.email gpg_opts = { encrypt: true, keys: {list.email => list.fingerprint}, sign: true, sign_as: list.admins.first.fingerprint } mail.gpg(gpg_opts) content_body = "This is a test\r\nAnd here are some umlauts:ÄäÖöÜüß" mail.charset = 'utf-8' mail.body = "x-list-name: #{list.email}\nX-resend: someone@example.org\n#{content_body}".encode('utf-8') mail.deliver encrypted_mail = Mail::TestMailer.deliveries.first Mail::TestMailer.deliveries.clear begin Schleuder::Runner.new().run(encrypted_mail.to_s, list.email) rescue SystemExit end raw = Mail::TestMailer.deliveries.first resent_message = raw.verify raw = Mail::TestMailer.deliveries.last message = Mail.create_message_to_list(raw.to_s, list.email, list).setup expect(message.to).to eql(['schleuder@example.org']) expect(message.to_s).to include("Resent: Unencrypted to someone@example.org") expect(message.parts[1].body.to_s.force_encoding(message.parts[1].charset)).to eql(content_body.encode(message.parts[1].charset)) expect(resent_message.to).to include("someone@example.org") expect(resent_message.to_s).not_to include("Resent: Unencrypted to someone@example.org") expect(resent_message.parts[0].body.to_s).to eql(content_body.encode(resent_message.parts[0].charset)) teardown_list_and_mailer(list) end it "x-resend with admin-notification" do list = create(:list, keywords_admin_notify: ['resend']) list.subscribe("schleuder@example.org", '59C71FB38AEE22E091C78259D06350440F759BD3', true) ENV['GNUPGHOME'] = list.listdir mail = Mail.new mail.to = list.email mail.from = list.admins.first.email gpg_opts = { encrypt: true, keys: {list.email => list.fingerprint}, sign: true, sign_as: list.admins.first.fingerprint } mail.gpg(gpg_opts) content_body = "Hello again!\n" mail.body = "x-list-name: #{list.email}\nX-resend: someone@example.org\n#{content_body}" mail.deliver encrypted_mail = Mail::TestMailer.deliveries.first Mail::TestMailer.deliveries.clear begin Schleuder::Runner.new().run(encrypted_mail.to_s, list.email) rescue SystemExit end raw = Mail::TestMailer.deliveries[1] notification = Mail.create_message_to_list(raw.to_s, list.email, list).setup raw = Mail::TestMailer.deliveries[2] message = Mail.create_message_to_list(raw.to_s, list.email, list).setup expect(Mail::TestMailer.deliveries.size).to eql(3) expect(notification.to).to eql(['schleuder@example.org']) expect(notification.first_plaintext_part.body.to_s).to eql("schleuder@example.org used the keyword 'resend' with the values 'someone@example.org' in a message sent to the list.") expect(message.to).to eql(['schleuder@example.org']) expect(message.to_s).to include("Resent: Unencrypted to someone@example.org") teardown_list_and_mailer(list) end it "x-resend with admin-notification and admin has delivery disabled" do list = create(:list, keywords_admin_notify: ['resend']) list.subscribe("user@example.org", "59C71FB38AEE22E091C78259D06350440F759BD3") list.subscribe("admin@example.org", '59C71FB38AEE22E091C78259D06350440F759BD3', true, false) ENV['GNUPGHOME'] = list.listdir mail = Mail.new mail.to = list.email mail.from = list.admins.first.email gpg_opts = { encrypt: true, keys: {list.email => list.fingerprint}, sign: true, sign_as: list.admins.first.fingerprint } mail.gpg(gpg_opts) content_body = "Hello again!\n" mail.body = "x-list-name: #{list.email}\nX-resend: someone@example.org\n#{content_body}" mail.deliver encrypted_mail = Mail::TestMailer.deliveries.first Mail::TestMailer.deliveries.clear begin Schleuder::Runner.new().run(encrypted_mail.to_s, list.email) rescue SystemExit end raw = Mail::TestMailer.deliveries[1] notification = Mail.create_message_to_list(raw.to_s, list.email, list).setup raw = Mail::TestMailer.deliveries[2] message = Mail.create_message_to_list(raw.to_s, list.email, list).setup expect(Mail::TestMailer.deliveries.size).to eql(3) expect(notification.to).to eql(['admin@example.org']) expect(notification.first_plaintext_part.body.to_s).to eql("admin@example.org used the keyword 'resend' with the values 'someone@example.org' in a message sent to the list.") expect(message.to).to eql(['user@example.org']) expect(message.to_s).to include("Resent: Unencrypted to someone@example.org") teardown_list_and_mailer(list) end it "x-resend without x-list-name" do list = create(:list) list.subscribe("schleuder@example.org", '59C71FB38AEE22E091C78259D06350440F759BD3', true) ENV['GNUPGHOME'] = list.listdir mail = Mail.new mail.to = list.email mail.from = list.admins.first.email gpg_opts = { encrypt: true, keys: {list.email => list.fingerprint}, sign: true, sign_as: list.admins.first.fingerprint } mail.gpg(gpg_opts) content_body = "Hello again!\n" mail.body = "X-resend: someone@example.org\n#{content_body}" mail.deliver encrypted_mail = Mail::TestMailer.deliveries.first Mail::TestMailer.deliveries.clear begin Schleuder::Runner.new().run(encrypted_mail.to_s, list.email) rescue SystemExit end raw = Mail::TestMailer.deliveries.first message = Mail.create_message_to_list(raw.to_s, list.email, list).setup expect(message.to).to eql(['schleuder@example.org']) expect(message.to_s).not_to include("Resent: Unencrypted to someone@example.org") expect(message.to_s).to include(%[Your message did not contain the required "X-LIST-NAME" keyword and was rejected.]) teardown_list_and_mailer(list) end it "x-resend-encrypted-only with matching key" do list = create(:list) list.subscribe("schleuder@example.org", '59C71FB38AEE22E091C78259D06350440F759BD3', true) ENV['GNUPGHOME'] = list.listdir list.import_key(File.read("spec/fixtures/bla_foo_key.txt")) mail = Mail.new mail.to = list.email mail.from = list.admins.first.email gpg_opts = { encrypt: true, keys: {list.email => list.fingerprint}, sign: true, sign_as: list.admins.first.fingerprint } mail.gpg(gpg_opts) content_body = "Hello again!\n" mail.body = "x-list-name: #{list.email}\nX-resend-encrypted-only: bla@foo\n#{content_body}" mail.deliver encrypted_mail = Mail::TestMailer.deliveries.first Mail::TestMailer.deliveries.clear begin Schleuder::Runner.new().run(encrypted_mail.to_s, list.email) rescue SystemExit end resent_message = Mail::TestMailer.deliveries.first raw = Mail::TestMailer.deliveries.last message = Mail.create_message_to_list(raw.to_s, list.email, list).setup expect(list.keys('bla@foo').size).to eql(1) expect(resent_message.to).to eql(['bla@foo']) expect(resent_message.content_type).to match(/^multipart\/encrypted.*application\/pgp-encrypted/) expect(message.first_plaintext_part.body.to_s).to include("Resent: Encrypted to bla@foo (87E65ED2081AE3D16BE4F0A5EBDBE899251F2412)") teardown_list_and_mailer(list) end it "x-resend-cc-encrypted-only with matching key" do list = create(:list) list.subscribe("schleuder@example.org", '59C71FB38AEE22E091C78259D06350440F759BD3', true) ENV['GNUPGHOME'] = list.listdir list.import_key(File.read("spec/fixtures/bla_foo_key.txt")) mail = Mail.new mail.to = list.email mail.from = list.admins.first.email gpg_opts = { encrypt: true, keys: {list.email => list.fingerprint}, sign: true, sign_as: list.admins.first.fingerprint } mail.gpg(gpg_opts) content_body = "Hello again!\n" mail.body = "x-list-name: #{list.email}\nX-resend-cc-encrypted-only: bla@foo\n#{content_body}" mail.deliver encrypted_mail = Mail::TestMailer.deliveries.first Mail::TestMailer.deliveries.clear begin Schleuder::Runner.new().run(encrypted_mail.to_s, list.email) rescue SystemExit end resent_message = Mail::TestMailer.deliveries.first raw = Mail::TestMailer.deliveries.last message = Mail.create_message_to_list(raw.to_s, list.email, list).setup expect(list.keys('bla@foo').size).to eql(1) expect(resent_message.cc).to eql(['bla@foo']) expect(resent_message.content_type).to match(/^multipart\/encrypted.*application\/pgp-encrypted/) expect(message.first_plaintext_part.body.to_s).to include("ResentCc: Encrypted to bla@foo (87E65ED2081AE3D16BE4F0A5EBDBE899251F2412)") teardown_list_and_mailer(list) end it "x-resend-cc-encrypted-only to 2 addresses with matching keys" do list = create(:list) list.subscribe("schleuder@example.org", '59C71FB38AEE22E091C78259D06350440F759BD3', true) ENV['GNUPGHOME'] = list.listdir list.import_key(File.read("spec/fixtures/bla_foo_key.txt")) mail = Mail.new mail.to = list.email mail.from = list.admins.first.email gpg_opts = { encrypt: true, keys: {list.email => list.fingerprint}, sign: true, sign_as: list.admins.first.fingerprint } mail.gpg(gpg_opts) content_body = "Hello again!\n" mail.body = "x-list-name: #{list.email}\nX-resend-cc-encrypted-only: schleuder@example.org bla@foo\n#{content_body}" mail.deliver encrypted_mail = Mail::TestMailer.deliveries.first Mail::TestMailer.deliveries.clear begin Schleuder::Runner.new().run(encrypted_mail.to_s, list.email) rescue SystemExit end resent_message = Mail::TestMailer.deliveries.first raw = Mail::TestMailer.deliveries.last message = Mail.create_message_to_list(raw.to_s, list.email, list).setup expect(list.keys('bla@foo').size).to eql(1) expect(resent_message.cc).to eql(['schleuder@example.org','bla@foo']) expect(resent_message.content_type).to match(/^multipart\/encrypted.*application\/pgp-encrypted/) expect(message.first_plaintext_part.body.to_s).to include("ResentCc: Encrypted to schleuder@example.org (59C71FB38AEE22E091C78259D06350440F759BD3), bla@foo (87E65ED2081AE3D16BE4F0A5EBDBE899251F2412)") teardown_list_and_mailer(list) end it "x-resend-cc-encrypted-only to 2 addresses with one missing keys" do list = create(:list) list.subscribe("schleuder@example.org", '59C71FB38AEE22E091C78259D06350440F759BD3', true) ENV['GNUPGHOME'] = list.listdir expect(list.keys('bla@foo').size).to eql(0) mail = Mail.new mail.to = list.email mail.from = list.admins.first.email gpg_opts = { encrypt: true, keys: {list.email => list.fingerprint}, sign: true, sign_as: list.admins.first.fingerprint } mail.gpg(gpg_opts) content_body = "Hello again!\n" mail.body = "x-list-name: #{list.email}\nX-resend-cc-encrypted-only: schleuder@example.org bla@foo\n#{content_body}" mail.deliver encrypted_mail = Mail::TestMailer.deliveries.first Mail::TestMailer.deliveries.clear begin Schleuder::Runner.new().run(encrypted_mail.to_s, list.email) rescue SystemExit end expect(Mail::TestMailer.deliveries.size).to eql(1) raw = Mail::TestMailer.deliveries.first message = Mail.create_message_to_list(raw.to_s, list.email, list).setup expect(message.first_plaintext_part.body.to_s).to include("Sig: Good signature from D06350440F759BD3 Schleuder TestUser Enc: Encrypted Error: Resending to failed (0 keys found, of which 0 can be used. Unencrypted sending not allowed). Error: Resending to aborted due to other errors.") teardown_list_and_mailer(list) end it "x-resend-cc-encrypted-only to 3 addresses with one missing keys" do list = create(:list) list.subscribe("schleuder@example.org", '59C71FB38AEE22E091C78259D06350440F759BD3', true) ENV['GNUPGHOME'] = list.listdir list.import_key(File.read("spec/fixtures/bla_foo_key.txt")) expect(list.keys('bla@foo').size).to eql(1) mail = Mail.new mail.to = list.email mail.from = list.admins.first.email gpg_opts = { encrypt: true, keys: {list.email => list.fingerprint}, sign: true, sign_as: list.admins.first.fingerprint } mail.gpg(gpg_opts) content_body = "Hello again!\n" mail.body = "x-list-name: #{list.email}\nX-resend-cc-encrypted-only: schleuder@example.org foo@bla bla@foo\n#{content_body}" mail.deliver encrypted_mail = Mail::TestMailer.deliveries.first Mail::TestMailer.deliveries.clear begin Schleuder::Runner.new().run(encrypted_mail.to_s, list.email) rescue SystemExit end expect(Mail::TestMailer.deliveries.size).to eql(1) raw = Mail::TestMailer.deliveries.first message = Mail.create_message_to_list(raw.to_s, list.email, list).setup expect(message.first_plaintext_part.body.to_s).to include("Error: Resending to failed (0 keys found, of which 0 can be used. Unencrypted sending not allowed). Error: Resending to aborted due to other errors. Error: Resending to aborted due to other errors.") teardown_list_and_mailer(list) end it "x-resend-cc to 2 addresses with missing keys" do list = create(:list) list.subscribe("schleuder@example.org", '59C71FB38AEE22E091C78259D06350440F759BD3', true) ENV['GNUPGHOME'] = list.listdir mail = Mail.new mail.to = list.email mail.from = list.admins.first.email gpg_opts = { encrypt: true, keys: {list.email => list.fingerprint}, sign: true, sign_as: list.admins.first.fingerprint } mail.gpg(gpg_opts) content_body = "Hello again!\n" mail.body = "x-list-name: #{list.email}\nX-resend-cc: foo@bla bla@foo\n#{content_body}" expect(list.keys('foo@bla').size).to eql(0) expect(list.keys('bla@foo').size).to eql(0) mail.deliver encrypted_mail = Mail::TestMailer.deliveries.first Mail::TestMailer.deliveries.clear begin Schleuder::Runner.new().run(encrypted_mail.to_s, list.email) rescue SystemExit end resent_message = Mail::TestMailer.deliveries.first raw = Mail::TestMailer.deliveries.last message = Mail.create_message_to_list(raw.to_s, list.email, list).setup expect(resent_message.cc).to eql(['foo@bla','bla@foo']) expect(resent_message.content_type).to match(/^multipart\/signed.*application\/pgp-signature/) expect(message.first_plaintext_part.body.to_s).to include("ResentCc: Unencrypted to foo@bla, bla@foo") teardown_list_and_mailer(list) end it "x-resend-cc to 2 addresses with one missing keys" do list = create(:list) list.subscribe("schleuder@example.org", '59C71FB38AEE22E091C78259D06350440F759BD3', true) ENV['GNUPGHOME'] = list.listdir list.import_key(File.read("spec/fixtures/bla_foo_key.txt")) mail = Mail.new mail.to = list.email mail.from = list.admins.first.email gpg_opts = { encrypt: true, keys: {list.email => list.fingerprint}, sign: true, sign_as: list.admins.first.fingerprint } mail.gpg(gpg_opts) content_body = "Hello again!\n" mail.body = "x-list-name: #{list.email}\nX-resend-cc: foo@bla bla@foo\n#{content_body}" expect(list.keys('foo@bla').size).to eql(0) expect(list.keys('bla@foo').size).to eql(1) mail.deliver encrypted_mail = Mail::TestMailer.deliveries.first Mail::TestMailer.deliveries.clear begin Schleuder::Runner.new().run(encrypted_mail.to_s, list.email) rescue SystemExit end resent_message = Mail::TestMailer.deliveries.first raw = Mail::TestMailer.deliveries.last message = Mail.create_message_to_list(raw.to_s, list.email, list).setup expect(resent_message.cc).to eql(['foo@bla','bla@foo']) expect(resent_message.content_type).to match(/^multipart\/signed.*application\/pgp-signature/) expect(message.first_plaintext_part.body.to_s).to include("ResentCc: Unencrypted to foo@bla, bla@foo") teardown_list_and_mailer(list) end it "x-resend-cc-encrypted-only to 2 addresses with missing keys" do list = create(:list) list.subscribe("schleuder@example.org", '59C71FB38AEE22E091C78259D06350440F759BD3', true) ENV['GNUPGHOME'] = list.listdir mail = Mail.new mail.to = list.email mail.from = list.admins.first.email gpg_opts = { encrypt: true, keys: {list.email => list.fingerprint}, sign: true, sign_as: list.admins.first.fingerprint } mail.gpg(gpg_opts) content_body = "Hello again!\n" mail.body = "x-list-name: #{list.email}\nX-resend-cc-encrypted-only: foo@bla bla@foo\n#{content_body}" expect(list.keys('foo@bla').size).to eql(0) expect(list.keys('bla@foo').size).to eql(0) mail.deliver encrypted_mail = Mail::TestMailer.deliveries.first Mail::TestMailer.deliveries.clear begin Schleuder::Runner.new().run(encrypted_mail.to_s, list.email) rescue SystemExit end expect(Mail::TestMailer.deliveries.size).to eql(1) raw = Mail::TestMailer.deliveries.first message = Mail.create_message_to_list(raw.to_s, list.email, list).setup expect(list.keys('bla@foo').size).to eql(0) expect(message.first_plaintext_part.body.to_s).to include("Error: Resending to failed (0 keys found, of which 0 can be used. Unencrypted sending not allowed). Error: Resending to failed (0 keys found, of which 0 can be used. Unencrypted sending not allowed).") teardown_list_and_mailer(list) end it "x-resend-encrypted-only with two matching keys, one of which is expired" do list = create(:list) list.subscribe("schleuder@example.org", '59C71FB38AEE22E091C78259D06350440F759BD3', true) ENV['GNUPGHOME'] = list.listdir list.import_key(File.read("spec/fixtures/expired_key.txt")) list.import_key(File.read("spec/fixtures/bla_foo_key.txt")) mail = Mail.new mail.to = list.email mail.from = list.admins.first.email gpg_opts = { encrypt: true, keys: {list.email => list.fingerprint}, sign: true, sign_as: list.admins.first.fingerprint } mail.gpg(gpg_opts) content_body = "Hello again!\n" mail.body = "x-list-name: #{list.email}\nX-resend-encrypted-only: bla@foo\n#{content_body}" mail.deliver encrypted_mail = Mail::TestMailer.deliveries.first Mail::TestMailer.deliveries.clear begin Schleuder::Runner.new().run(encrypted_mail.to_s, list.email) rescue SystemExit end resent_message = Mail::TestMailer.deliveries.first raw = Mail::TestMailer.deliveries.last message = Mail.create_message_to_list(raw.to_s, list.email, list).setup expect(list.keys('bla@foo').size).to eql(2) expect(resent_message.to).to eql(['bla@foo']) expect(resent_message.content_type).to match(/^multipart\/encrypted.*application\/pgp-encrypted/) expect(message.first_plaintext_part.body.to_s).to include("Resent: Encrypted to bla@foo (87E65ED2081AE3D16BE4F0A5EBDBE899251F2412)") teardown_list_and_mailer(list) end it "x-resend-unencrypted with matching key" do list = create(:list) list.subscribe("schleuder@example.org", '59C71FB38AEE22E091C78259D06350440F759BD3', true) ENV['GNUPGHOME'] = list.listdir list.import_key(File.read("spec/fixtures/bla_foo_key.txt")) mail = Mail.new mail.to = list.email mail.from = list.admins.first.email gpg_opts = { encrypt: true, keys: {list.email => list.fingerprint}, sign: true, sign_as: list.admins.first.fingerprint } mail.gpg(gpg_opts) content_body = "Hello again!\n" mail.body = "x-list-name: #{list.email}\nX-resend-unencrypted: bla@foo\n#{content_body}" mail.deliver encrypted_mail = Mail::TestMailer.deliveries.first Mail::TestMailer.deliveries.clear begin Schleuder::Runner.new().run(encrypted_mail.to_s, list.email) rescue SystemExit end resent_message = Mail::TestMailer.deliveries.first raw = Mail::TestMailer.deliveries.last message = Mail.create_message_to_list(raw.to_s, list.email, list).setup expect(list.keys('bla@foo').size).to eql(1) expect(resent_message.to).to eql(['bla@foo']) expect(resent_message.content_type).to_not match(/^multipart\/encrypted.*application\/pgp-encrypted/) expect(resent_message.first_plaintext_part.body.to_s).to include('Hello again!') expect(message.first_plaintext_part.body.to_s).to include("Resent: Unencrypted to bla@foo") teardown_list_and_mailer(list) end it "x-resend-encrypted-only with expired key" do list = create(:list) list.subscribe("schleuder@example.org", '59C71FB38AEE22E091C78259D06350440F759BD3', true) ENV['GNUPGHOME'] = list.listdir list.import_key(File.read("spec/fixtures/expired_key.txt")) mail = Mail.new mail.to = list.email mail.from = list.admins.first.email gpg_opts = { encrypt: true, keys: {list.email => list.fingerprint}, sign: true, sign_as: list.admins.first.fingerprint } mail.gpg(gpg_opts) content_body = "Hello again!\n" mail.body = "x-list-name: #{list.email}\nX-resend-encrypted-only: bla@foo\n#{content_body}" mail.deliver encrypted_mail = Mail::TestMailer.deliveries.first Mail::TestMailer.deliveries.clear begin Schleuder::Runner.new().run(encrypted_mail.to_s, list.email) rescue SystemExit end raw = Mail::TestMailer.deliveries.first message = Mail.create_message_to_list(raw.to_s, list.email, list).setup expect(list.keys('bla@foo').size).to eql(1) expect(message.first_plaintext_part.to_s).to include("Error: Resending to failed (1 keys found, of which 0 can be used.\r\n Unencrypted sending not allowed).") teardown_list_and_mailer(list) end it "x-resend-cc-encrypted-only with expired key" do list = create(:list) list.subscribe("schleuder@example.org", '59C71FB38AEE22E091C78259D06350440F759BD3', true) ENV['GNUPGHOME'] = list.listdir list.import_key(File.read("spec/fixtures/expired_key.txt")) mail = Mail.new mail.to = list.email mail.from = list.admins.first.email gpg_opts = { encrypt: true, keys: {list.email => list.fingerprint}, sign: true, sign_as: list.admins.first.fingerprint } mail.gpg(gpg_opts) content_body = "Hello again!\n" mail.body = "x-list-name: #{list.email}\nX-resend-cc-encrypted-only: bla@foo\n#{content_body}" mail.deliver encrypted_mail = Mail::TestMailer.deliveries.first Mail::TestMailer.deliveries.clear begin Schleuder::Runner.new().run(encrypted_mail.to_s, list.email) rescue SystemExit end raw = Mail::TestMailer.deliveries.first message = Mail.create_message_to_list(raw.to_s, list.email, list).setup expect(list.keys('bla@foo').size).to eql(1) expect(message.first_plaintext_part.to_s).to include("Error: Resending to failed (1 keys found, of which 0 can be used.\r\n Unencrypted sending not allowed).") teardown_list_and_mailer(list) end it "x-resend with wrong x-list-name" do list = create(:list) list.subscribe("schleuder@example.org", '59C71FB38AEE22E091C78259D06350440F759BD3', true) ENV['GNUPGHOME'] = list.listdir mail = Mail.new mail.to = list.email mail.from = list.admins.first.email gpg_opts = { encrypt: true, keys: {list.email => list.fingerprint}, sign: true, sign_as: list.admins.first.fingerprint } mail.gpg(gpg_opts) content_body = "Hello again!\n" mail.body = "x-list-name: somethingelse@example.org\nX-resend: someone@example.org\n#{content_body}" mail.deliver encrypted_mail = Mail::TestMailer.deliveries.first Mail::TestMailer.deliveries.clear begin Schleuder::Runner.new().run(encrypted_mail.to_s, list.email) rescue SystemExit end raw = Mail::TestMailer.deliveries.first message = Mail.create_message_to_list(raw.to_s, list.email, list).setup expect(message.to).to eql(['schleuder@example.org']) expect(message.to_s).not_to include("Resent: Unencrypted to someone@example.org") expect(message.to_s).to include(%[Your message contained an incorrect "X-LIST-NAME" keyword. The keyword argument must match the email address of this list.]) teardown_list_and_mailer(list) end it "x-resend with invalid recipient" do list = create(:list) list.subscribe("schleuder@example.org", '59C71FB38AEE22E091C78259D06350440F759BD3', true) ENV['GNUPGHOME'] = list.listdir mail = Mail.new mail.to = list.email mail.from = list.admins.first.email gpg_opts = { encrypt: true, keys: {list.email => list.fingerprint}, sign: true, sign_as: list.admins.first.fingerprint } mail.gpg(gpg_opts) content_body = "Hello again!\n" invalid_recipient = '`ls`bla' mail.body = "x-list-name: #{list.email}\nX-resend: #{invalid_recipient}\n#{content_body}" mail.deliver encrypted_mail = Mail::TestMailer.deliveries.first Mail::TestMailer.deliveries.clear begin Schleuder::Runner.new().run(encrypted_mail.to_s, list.email) rescue SystemExit end delivered_emails = Mail::TestMailer.deliveries raw = delivered_emails.first message = Mail.create_message_to_list(raw.to_s, list.email, list).setup expect(delivered_emails.size).to eql(1) expect(message.to_s).not_to include("Resent: Unencrypted to someone@example.org") expect(message.to_s).to include("Error: Invalid email-address for resending: #{invalid_recipient}") teardown_list_and_mailer(list) end it "x-sign-this with inline text" do list = create(:list) list.subscribe("schleuder@example.org", '59C71FB38AEE22E091C78259D06350440F759BD3', true) ENV['GNUPGHOME'] = list.listdir mail = Mail.new mail.to = list.request_address mail.from = list.admins.first.email gpg_opts = { encrypt: true, keys: {list.request_address => list.fingerprint}, sign: true, sign_as: list.admins.first.fingerprint } mail.gpg(gpg_opts) signed_text = "signed\nsigned\nsigned\n\n" mail.body = "x-list-name: #{list.email}\nx-sign-this:\n#{signed_text}" mail.deliver encrypted_mail = Mail::TestMailer.deliveries.first Mail::TestMailer.deliveries.clear begin Schleuder::Runner.new().run(encrypted_mail.to_s, list.request_address) rescue SystemExit end raw = Mail::TestMailer.deliveries.first message = Mail.create_message_to_list(raw.to_s, list.email, list).setup expect(message.to_s.gsub("\r", '')).to match(/BEGIN PGP SIGNED MESSAGE-----\nHash: SHA(256|512)\n\n#{signed_text}-----BEGIN PGP SIGNATURE/) teardown_list_and_mailer(list) end it "x-sign-this with attachments" do list = create(:list) list.subscribe("schleuder@example.org", '59C71FB38AEE22E091C78259D06350440F759BD3', true) ENV['GNUPGHOME'] = list.listdir mail = Mail.new mail.to = list.request_address mail.from = list.admins.first.email gpg_opts = { encrypt: true, keys: {list.request_address => list.fingerprint}, sign: true, sign_as: list.admins.first.fingerprint } mail.gpg(gpg_opts) keywords = Mail::Part.new keywords.body = "\n\nx-list-name: #{list.email}\nx-sign-this:" mail.parts << keywords signed_content = File.read('spec/fixtures/example_key.txt') mail.attachments['example_key.txt'] = { mime_type: 'application/pgp-key', content: signed_content } mail.deliver encrypted_mail = Mail::TestMailer.deliveries.first Mail::TestMailer.deliveries.clear begin Schleuder::Runner.new().run(encrypted_mail.to_s, list.request_address) rescue SystemExit end raw = Mail::TestMailer.deliveries.first message = Mail.create_message_to_list(raw.to_s, list.email, list).setup signature = message.attachments.first.body.to_s # list.gpg.verify() results in a "Bad Signature". The sign-this plugin # also uses GPGME::Crypto, apparently that makes a difference. crypto = GPGME::Crypto.new verification_string = '' crypto.verify(signature, {signed_text: signed_content}) do |sig| verification_string = sig.to_s end expect(message.to_s).to include("Find the signatures attached.") expect(message.attachments.size).to eql(1) expect(message.attachments.first.filename).to eql("example_key.txt.sig") expect(verification_string).to include("Good signature from D06350440F759BD3") teardown_list_and_mailer(list) end it "x-list-key with arbitrary email-sub-string" do list = create(:list) list.subscribe("schleuder@example.org", '59C71FB38AEE22E091C78259D06350440F759BD3', true) ENV['GNUPGHOME'] = list.listdir mail = Mail.new mail.to = list.request_address mail.from = list.admins.first.email gpg_opts = { encrypt: true, keys: {list.request_address => list.fingerprint}, sign: true, sign_as: list.admins.first.fingerprint } mail.gpg(gpg_opts) mail.body = "x-list-name: #{list.email}\nX-list-KEYs: der@ex" mail.deliver encrypted_mail = Mail::TestMailer.deliveries.first Mail::TestMailer.deliveries.clear begin Schleuder::Runner.new().run(encrypted_mail.to_s, list.request_address) rescue SystemExit end raw = Mail::TestMailer.deliveries.first message = Mail.create_message_to_list(raw.to_s, list.request_address, list).setup expect(message.to).to eql(['schleuder@example.org']) expect(message.to_s).to match(/pub 4096R\/59C71FB38AEE22E091C78259D06350440F759BD3 \d{4}-\d{2}-\d{2}/) expect(message.to_s.scan(/^pub /).size).to eql(1) teardown_list_and_mailer(list) end it "x-list-key with correctly prefixed email-sub-string" do list = create(:list) list.subscribe("schleuder@example.org", '59C71FB38AEE22E091C78259D06350440F759BD3', true) ENV['GNUPGHOME'] = list.listdir mail = Mail.new mail.to = list.request_address mail.from = list.admins.first.email gpg_opts = { encrypt: true, keys: {list.request_address => list.fingerprint}, sign: true, sign_as: list.admins.first.fingerprint } mail.gpg(gpg_opts) mail.body = "x-list-name: #{list.email}\nX-list-KEYs: @schleuder" mail.deliver encrypted_mail = Mail::TestMailer.deliveries.first Mail::TestMailer.deliveries.clear begin Schleuder::Runner.new().run(encrypted_mail.to_s, list.request_address) rescue SystemExit end raw = Mail::TestMailer.deliveries.first message = Mail.create_message_to_list(raw.to_s, list.request_address, list).setup expect(message.to).to eql(['schleuder@example.org']) expect(message.to_s).to match(/pub 4096R\/59C71FB38AEE22E091C78259D06350440F759BD3 \d{4}-\d{2}-\d{2}/) expect(message.to_s.scan(/^pub /).size).to eql(1) teardown_list_and_mailer(list) end it "x-list-key with prefixed fingerprint" do list = create(:list) list.subscribe("schleuder@example.org", '59C71FB38AEE22E091C78259D06350440F759BD3', true) ENV['GNUPGHOME'] = list.listdir mail = Mail.new mail.to = list.request_address mail.from = list.admins.first.email gpg_opts = { encrypt: true, keys: {list.request_address => list.fingerprint}, sign: true, sign_as: list.admins.first.fingerprint } mail.gpg(gpg_opts) mail.body = "x-list-name: #{list.email}\nX-list-KEYs: 0x59C71FB38AEE22E091C78259D06350440F759BD3" mail.deliver encrypted_mail = Mail::TestMailer.deliveries.first Mail::TestMailer.deliveries.clear begin Schleuder::Runner.new().run(encrypted_mail.to_s, list.request_address) rescue SystemExit end raw = Mail::TestMailer.deliveries.first message = Mail.create_message_to_list(raw.to_s, list.request_address, list).setup expect(message.to).to eql(['schleuder@example.org']) expect(message.to_s).to match(/pub 4096R\/59C71FB38AEE22E091C78259D06350440F759BD3 \d{4}-\d{2}-\d{2}/) expect(message.to_s.scan(/^pub /).size).to eql(1) teardown_list_and_mailer(list) end it "x-get-key with valid argument" do list = create(:list) list.subscribe("schleuder@example.org", '59C71FB38AEE22E091C78259D06350440F759BD3', true) ENV['GNUPGHOME'] = list.listdir mail = Mail.new mail.to = list.request_address mail.from = list.admins.first.email gpg_opts = { encrypt: true, keys: {list.request_address => list.fingerprint}, sign: true, sign_as: list.admins.first.fingerprint } mail.gpg(gpg_opts) mail.body = "x-list-name: #{list.email}\nX-GET-KEY: 0x59C71FB38AEE22E091C78259D06350440F759BD3" mail.deliver encrypted_mail = Mail::TestMailer.deliveries.first Mail::TestMailer.deliveries.clear begin Schleuder::Runner.new().run(encrypted_mail.to_s, list.request_address) rescue SystemExit end raw = Mail::TestMailer.deliveries.first message = Mail.create_message_to_list(raw.to_s, list.request_address, list).setup expect(message.to).to eql(['schleuder@example.org']) expect(message.to_s).to match(/pub 4096R\/59C71FB38AEE22E091C78259D06350440F759BD3 \d{4}-\d{2}-\d{2}/) expect(message.to_s).to include("-----BEGIN PGP PUBLIC KEY") teardown_list_and_mailer(list) end it "x-get-key with invalid argument" do list = create(:list) list.subscribe("schleuder@example.org", '59C71FB38AEE22E091C78259D06350440F759BD3', true) ENV['GNUPGHOME'] = list.listdir mail = Mail.new mail.to = list.request_address mail.from = list.admins.first.email gpg_opts = { encrypt: true, keys: {list.request_address => list.fingerprint}, sign: true, sign_as: list.admins.first.fingerprint } mail.gpg(gpg_opts) mail.body = "x-list-name: #{list.email}\nX-get-KEY: blabla" mail.deliver encrypted_mail = Mail::TestMailer.deliveries.first Mail::TestMailer.deliveries.clear begin Schleuder::Runner.new().run(encrypted_mail.to_s, list.request_address) rescue SystemExit end raw = Mail::TestMailer.deliveries.first message = Mail.create_message_to_list(raw.to_s, list.request_address, list).setup expect(message.to).to eql(['schleuder@example.org']) expect(message.to_s).to include("No match found for") expect(message.to_s).not_to include("-----BEGIN PGP PUBLIC KEY") teardown_list_and_mailer(list) end it "x-get-key with empty argument" do list = create(:list) list.subscribe("schleuder@example.org", '59C71FB38AEE22E091C78259D06350440F759BD3', true) ENV['GNUPGHOME'] = list.listdir mail = Mail.new mail.to = list.request_address mail.from = list.admins.first.email gpg_opts = { encrypt: true, keys: {list.request_address => list.fingerprint}, sign: true, sign_as: list.admins.first.fingerprint } mail.gpg(gpg_opts) mail.body = "x-list-name: #{list.email}\nX-get-KEY:" mail.deliver encrypted_mail = Mail::TestMailer.deliveries.first Mail::TestMailer.deliveries.clear begin Schleuder::Runner.new().run(encrypted_mail.to_s, list.request_address) rescue SystemExit end raw = Mail::TestMailer.deliveries.first message = Mail.create_message_to_list(raw.to_s, list.request_address, list).setup expect(message.to).to eql(['schleuder@example.org']) expect(message.to_s).to include("Your message resulted in no output") expect(message.to_s).not_to include("-----BEGIN PGP PUBLIC KEY") teardown_list_and_mailer(list) end it "x-delete-key with valid argument" do list = create(:list) list.subscribe("schleuder@example.org", '59C71FB38AEE22E091C78259D06350440F759BD3', true) list.import_key(File.read('spec/fixtures/example_key.txt')) list_keys_num = list.keys.size ENV['GNUPGHOME'] = list.listdir mail = Mail.new mail.to = list.request_address mail.from = list.admins.first.email gpg_opts = { encrypt: true, keys: {list.request_address => list.fingerprint}, sign: true, sign_as: list.admins.first.fingerprint } mail.gpg(gpg_opts) mail.body = "x-list-name: #{list.email}\nX-delete-KEY: C4D60F8833789C7CAA44496FD3FFA6613AB10ECE" mail.deliver encrypted_mail = Mail::TestMailer.deliveries.first Mail::TestMailer.deliveries.clear begin Schleuder::Runner.new().run(encrypted_mail.to_s, list.request_address) rescue SystemExit end raw = Mail::TestMailer.deliveries.first message = Mail.create_message_to_list(raw.to_s, list.request_address, list).setup expect(list.keys.size).to eql(list_keys_num - 1) expect(message.to).to eql(['schleuder@example.org']) expect(message.first_plaintext_part.body.to_s).to match(/^This key was deleted:\n0xC4D60F8833789C7CAA44496FD3FFA6613AB10ECE schleuder2@example.org \d{4}-\d{2}-\d{2}\n$/) teardown_list_and_mailer(list) end it "x-delete-key with invalid argument" do list = create(:list) list.subscribe("schleuder@example.org", '59C71FB38AEE22E091C78259D06350440F759BD3', true) list.import_key(File.read('spec/fixtures/example_key.txt')) list_keys_num = list.keys.size ENV['GNUPGHOME'] = list.listdir mail = Mail.new mail.to = list.request_address mail.from = list.admins.first.email gpg_opts = { encrypt: true, keys: {list.request_address => list.fingerprint}, sign: true, sign_as: list.admins.first.fingerprint } mail.gpg(gpg_opts) mail.body = "x-list-name: #{list.email}\nX-delete-KEY: lala" mail.deliver encrypted_mail = Mail::TestMailer.deliveries.first Mail::TestMailer.deliveries.clear begin Schleuder::Runner.new().run(encrypted_mail.to_s, list.request_address) rescue SystemExit end raw = Mail::TestMailer.deliveries.first message = Mail.create_message_to_list(raw.to_s, list.request_address, list).setup expect(list.keys.size).to eql(list_keys_num) expect(message.to).to eql(['schleuder@example.org']) expect(message.to_s).to include("No match found for") expect(message.to_s).not_to include("This key was deleted:") teardown_list_and_mailer(list) end it "x-delete-key with not distinctly matching argument" do list = create(:list) list.subscribe("schleuder@example.org", '59C71FB38AEE22E091C78259D06350440F759BD3', true) list.import_key(File.read('spec/fixtures/example_key.txt')) list_keys_num = list.keys.size ENV['GNUPGHOME'] = list.listdir mail = Mail.new mail.to = list.request_address mail.from = list.admins.first.email gpg_opts = { encrypt: true, keys: {list.request_address => list.fingerprint}, sign: true, sign_as: list.admins.first.fingerprint } mail.gpg(gpg_opts) mail.body = "x-list-name: #{list.email}\nX-delete-KEY: schleuder" mail.deliver encrypted_mail = Mail::TestMailer.deliveries.first Mail::TestMailer.deliveries.clear begin Schleuder::Runner.new().run(encrypted_mail.to_s, list.request_address) rescue SystemExit end raw = Mail::TestMailer.deliveries.first message = Mail.create_message_to_list(raw.to_s, list.request_address, list).setup expect(list.keys.size).to eql(list_keys_num) expect(message.to).to eql(['schleuder@example.org']) expect(message.to_s).to include("Too many matching keys for ") expect(message.to_s).not_to include("Deleted") teardown_list_and_mailer(list) end it "x-delete-key without argument" do list = create(:list) list.subscribe("schleuder@example.org", '59C71FB38AEE22E091C78259D06350440F759BD3', true) list.import_key(File.read('spec/fixtures/example_key.txt')) list_keys_num = list.keys.size ENV['GNUPGHOME'] = list.listdir mail = Mail.new mail.to = list.request_address mail.from = list.admins.first.email gpg_opts = { encrypt: true, keys: {list.request_address => list.fingerprint}, sign: true, sign_as: list.admins.first.fingerprint } mail.gpg(gpg_opts) mail.body = "x-list-name: #{list.email}\nX-delete-KEY:" mail.deliver encrypted_mail = Mail::TestMailer.deliveries.first Mail::TestMailer.deliveries.clear begin Schleuder::Runner.new().run(encrypted_mail.to_s, list.request_address) rescue SystemExit end raw = Mail::TestMailer.deliveries.first message = Mail.create_message_to_list(raw.to_s, list.request_address, list).setup expect(list.keys.size).to eql(list_keys_num) expect(message.to_s).not_to include("translation missing") expect(message.first_plaintext_part.body.to_s).to eql(I18n.t("plugins.key_management.delete_key_requires_arguments")) teardown_list_and_mailer(list) end it "x-get-logfile with debug level sends non-empty logfile" do list = create(:list) list.update_attribute(:log_level, 'debug') list.subscribe("schleuder@example.org", '59C71FB38AEE22E091C78259D06350440F759BD3', true) ENV['GNUPGHOME'] = list.listdir mail = Mail.new mail.to = list.request_address mail.from = list.admins.first.email gpg_opts = { encrypt: true, keys: {list.request_address => list.fingerprint}, sign: true, sign_as: list.admins.first.fingerprint } mail.gpg(gpg_opts) mail.body = "x-list-name: #{list.email}\nX-get-logfile" mail.deliver encrypted_mail = Mail::TestMailer.deliveries.first Mail::TestMailer.deliveries.clear begin Schleuder::Runner.new().run(encrypted_mail.to_s, list.request_address) rescue SystemExit end raw = Mail::TestMailer.deliveries.first message = Mail.create_message_to_list(raw.to_s, list.request_address, list).setup expect(message.to).to eql(['schleuder@example.org']) expect(message.parts.last.body.to_s.lines.size).to be > 1 expect(message.parts.last.body.to_s).to include("Logfile created on") expect(message.parts.last.body.to_s).to include("DEBUG") teardown_list_and_mailer(list) end it "x-get-logfile with error-level sends empty logfile" do list = create(:list) list.update_attribute(:log_level, 'error') list.subscribe("schleuder@example.org", '59C71FB38AEE22E091C78259D06350440F759BD3', true) ENV['GNUPGHOME'] = list.listdir mail = Mail.new mail.to = list.request_address mail.from = list.admins.first.email gpg_opts = { encrypt: true, keys: {list.request_address => list.fingerprint}, sign: true, sign_as: list.admins.first.fingerprint } mail.gpg(gpg_opts) mail.body = "x-list-name: #{list.email}\nX-get-logfile" mail.deliver encrypted_mail = Mail::TestMailer.deliveries.first Mail::TestMailer.deliveries.clear begin Schleuder::Runner.new().run(encrypted_mail.to_s, list.request_address) rescue SystemExit end raw = Mail::TestMailer.deliveries.first message = Mail.create_message_to_list(raw.to_s, list.request_address, list).setup expect(message.to).to eql(['schleuder@example.org']) expect(message.first_plaintext_part.body.to_s.lines.size).to eql(1) expect(message.body.to_s).to include("Logfile created on") teardown_list_and_mailer(list) end it "x-attach-listkey" do list = create(:list, log_level: 'debug') list.subscribe("schleuder@example.org", '59C71FB38AEE22E091C78259D06350440F759BD3', true) ENV['GNUPGHOME'] = list.listdir mail = Mail.new mail.to = list.email mail.from = list.admins.first.email gpg_opts = { encrypt: true, keys: {list.email => list.fingerprint}, sign: true, sign_as: list.admins.first.fingerprint } mail.gpg(gpg_opts) content_body = "something something list-key" mail.body = "x-list-name: #{list.email}\nX-attach-listkey\n#{content_body}" mail.deliver encrypted_mail = Mail::TestMailer.deliveries.first Mail::TestMailer.deliveries.clear begin Schleuder::Runner.new().run(encrypted_mail.to_s, list.email) rescue SystemExit end raw = Mail::TestMailer.deliveries.first message = Mail.create_message_to_list(raw.to_s, list.email, list).setup expect(message.parts.length).to eql(2) expect(message.parts.last.parts.length).to eql(2) expect(message.parts.last.parts.first.body.to_s).to eql(content_body) expect(message.parts.last.parts.last.content_type.to_s).to eql("application/pgp-keys") expect(message.parts.last.parts.last.body.decoded).to match(/pub 4096R\/59C71FB38AEE22E091C78259D06350440F759BD3 \d{4}-\d{2}-\d{2}/) expect(message.parts.last.parts.last.body.decoded).to include("-----BEGIN PGP PUBLIC KEY BLOCK-----") expect(message.parts.last.parts.last.body.decoded).to include("mQINBFhGvz0BEADXbbTWo/PStyTznAo/f1UobY0EiVPNKNERvYua2Pnq8BwOQ5bS") teardown_list_and_mailer(list) end it 'x-attach-listkey from Thunderbird with protected headers' do list = create(:list, email: 'testlist@example.net') list.subscribe('schleuder@example.org', '59C71FB38AEE22E091C78259D06350440F759BD3', true) encrypted_mail = File.read('spec/fixtures/mails/attach-list-key-thunderbird.eml') res = nil begin res = Schleuder::Runner.new().run(encrypted_mail.to_s, list.email) rescue SystemExit end raw = Mail::TestMailer.deliveries.first message = Mail.create_message_to_list(raw.to_s, list.email, list).setup expect(message.parts.length).to eql(2) expect(message.parts.last.parts.length).to eql(2) expect(message.parts.last.parts.first.decoded).to eql("Hallo\r\n\r\nkurz mal testen, wie ein resend mail, wo zusätzlich der listkey attached\r\nist bei euch so ankommt.\r\n\r\nich habe das gefühl hier ist as broken.\r\n\r\n\r\n\r\n\r\n") expect(message.parts.last.parts.last.content_type.to_s).to eql('application/pgp-keys') expect(message.parts.last.parts.last.body.decoded).to match(/pub 4096R\/59C71FB38AEE22E091C78259D06350440F759BD3 \d{4}-\d{2}-\d{2}/) expect(message.parts.last.parts.last.body.decoded).to include('-----BEGIN PGP PUBLIC KEY BLOCK-----') expect(message.parts.last.parts.last.body.decoded).to include('mQINBFhGvz0BEADXbbTWo/PStyTznAo/f1UobY0EiVPNKNERvYua2Pnq8BwOQ5bS') teardown_list_and_mailer(list) end it "x-get-version" do list = create(:list) list.subscribe("schleuder@example.org", '59C71FB38AEE22E091C78259D06350440F759BD3', true) ENV['GNUPGHOME'] = list.listdir mail = Mail.new mail.to = list.request_address mail.from = list.admins.first.email gpg_opts = { encrypt: true, keys: {list.request_address => list.fingerprint}, sign: true, sign_as: list.admins.first.fingerprint } mail.gpg(gpg_opts) mail.body = "x-list-name: #{list.email}\nX-get-version" mail.deliver encrypted_mail = Mail::TestMailer.deliveries.first Mail::TestMailer.deliveries.clear begin Schleuder::Runner.new().run(encrypted_mail.to_s, list.request_address) rescue SystemExit end raw = Mail::TestMailer.deliveries.first message = Mail.create_message_to_list(raw.to_s, list.request_address, list).setup expect(message.to).to eql(['schleuder@example.org']) expect(message.first_plaintext_part.body.to_s.lines.size).to eql(1) expect(message.first_plaintext_part.body.to_s).to eql(Schleuder::VERSION) teardown_list_and_mailer(list) end it "x-get-version with deprecated x-listname keyword" do list = create(:list) list.subscribe("schleuder@example.org", '59C71FB38AEE22E091C78259D06350440F759BD3', true) ENV['GNUPGHOME'] = list.listdir mail = Mail.new mail.to = list.request_address mail.from = list.admins.first.email gpg_opts = { encrypt: true, keys: {list.request_address => list.fingerprint}, sign: true, sign_as: list.admins.first.fingerprint } mail.gpg(gpg_opts) mail.body = "x-listname: #{list.email}\nX-get-version" mail.deliver encrypted_mail = Mail::TestMailer.deliveries.first Mail::TestMailer.deliveries.clear begin Schleuder::Runner.new().run(encrypted_mail.to_s, list.request_address) rescue SystemExit end raw = Mail::TestMailer.deliveries.first message = Mail.create_message_to_list(raw.to_s, list.request_address, list).setup expect(message.to).to eql(['schleuder@example.org']) expect(message.first_plaintext_part.body.to_s.lines.size).to eql(1) expect(message.first_plaintext_part.body.to_s).to eql(Schleuder::VERSION) teardown_list_and_mailer(list) end it "x-get-version with delivery disabled" do list = create(:list) list.subscribe("schleuder@example.org", '59C71FB38AEE22E091C78259D06350440F759BD3', true, false) ENV['GNUPGHOME'] = list.listdir mail = Mail.new mail.to = list.request_address mail.from = list.admins.first.email gpg_opts = { encrypt: true, keys: {list.request_address => list.fingerprint}, sign: true, sign_as: list.admins.first.fingerprint } mail.gpg(gpg_opts) mail.body = "x-listname: #{list.email}\nX-get-version" mail.deliver encrypted_mail = Mail::TestMailer.deliveries.first Mail::TestMailer.deliveries.clear begin Schleuder::Runner.new().run(encrypted_mail.to_s, list.request_address) rescue SystemExit end raw = Mail::TestMailer.deliveries.first message = Mail.create_message_to_list(raw.to_s, list.request_address, list).setup expect(message.to).to eql(['schleuder@example.org']) expect(message.first_plaintext_part.body.to_s.lines.size).to eql(1) expect(message.first_plaintext_part.body.to_s).to eql(Schleuder::VERSION) teardown_list_and_mailer(list) end it "x-list-keys without arguments" do list = create(:list) list.subscribe("schleuder@example.org", '59C71FB38AEE22E091C78259D06350440F759BD3', true) list.import_key(File.read('spec/fixtures/example_key.txt')) list.import_key(File.read('spec/fixtures/bla_foo_key.txt')) ENV['GNUPGHOME'] = list.listdir mail = Mail.new mail.to = list.request_address mail.from = list.admins.first.email gpg_opts = { encrypt: true, keys: {list.request_address => list.fingerprint}, sign: true, sign_as: list.admins.first.fingerprint } mail.gpg(gpg_opts) mail.body = "x-list-name: #{list.email}\nX-list-keys" mail.deliver encrypted_mail = Mail::TestMailer.deliveries.first Mail::TestMailer.deliveries.clear begin Schleuder::Runner.new().run(encrypted_mail.to_s, list.request_address) rescue SystemExit end raw = Mail::TestMailer.deliveries.first message = Mail.create_message_to_list(raw.to_s, list.request_address, list).setup expect(message.first_plaintext_part.body.to_s.lines.size).to eql(16) expect(message.first_plaintext_part.body.to_s).to include("59C71FB38AEE22E091C78259D06350440F759BD3") expect(message.first_plaintext_part.body.to_s).to include("C4D60F8833789C7CAA44496FD3FFA6613AB10ECE") expect(message.first_plaintext_part.body.to_s).to include("87E65ED2081AE3D16BE4F0A5EBDBE899251F2412") teardown_list_and_mailer(list) end it "x-list-keys with one argument" do list = create(:list) list.subscribe("schleuder@example.org", '59C71FB38AEE22E091C78259D06350440F759BD3', true) list.import_key(File.read('spec/fixtures/example_key.txt')) list.import_key(File.read('spec/fixtures/bla_foo_key.txt')) ENV['GNUPGHOME'] = list.listdir mail = Mail.new mail.to = list.request_address mail.from = list.admins.first.email gpg_opts = { encrypt: true, keys: {list.request_address => list.fingerprint}, sign: true, sign_as: list.admins.first.fingerprint } mail.gpg(gpg_opts) mail.body = "x-list-name: #{list.email}\nX-list-keys schleuder2" mail.deliver encrypted_mail = Mail::TestMailer.deliveries.first Mail::TestMailer.deliveries.clear begin Schleuder::Runner.new().run(encrypted_mail.to_s, list.request_address) rescue SystemExit end raw = Mail::TestMailer.deliveries.first message = Mail.create_message_to_list(raw.to_s, list.request_address, list).setup expect(message.first_plaintext_part.body.to_s.lines.size).to eql(4) expect(message.first_plaintext_part.body.to_s).not_to include("59C71FB38AEE22E091C78259D06350440F759BD3") expect(message.first_plaintext_part.body.to_s).to include("C4D60F8833789C7CAA44496FD3FFA6613AB10ECE") expect(message.first_plaintext_part.body.to_s).not_to include("87E65ED2081AE3D16BE4F0A5EBDBE899251F2412") teardown_list_and_mailer(list) end it "x-list-keys with two arguments" do list = create(:list) list.subscribe("schleuder@example.org", '59C71FB38AEE22E091C78259D06350440F759BD3', true) list.import_key(File.read('spec/fixtures/example_key.txt')) list.import_key(File.read('spec/fixtures/bla_foo_key.txt')) ENV['GNUPGHOME'] = list.listdir mail = Mail.new mail.to = list.request_address mail.from = list.admins.first.email gpg_opts = { encrypt: true, keys: {list.request_address => list.fingerprint}, sign: true, sign_as: list.admins.first.fingerprint } mail.gpg(gpg_opts) mail.body = "x-list-name: #{list.email}\nX-list-keys schleuder2 bla" mail.deliver encrypted_mail = Mail::TestMailer.deliveries.first Mail::TestMailer.deliveries.clear begin Schleuder::Runner.new().run(encrypted_mail.to_s, list.request_address) rescue SystemExit end raw = Mail::TestMailer.deliveries.first message = Mail.create_message_to_list(raw.to_s, list.request_address, list).setup expect(message.first_plaintext_part.body.to_s.lines.size).to eql(10) expect(message.first_plaintext_part.body.to_s).not_to include("59C71FB38AEE22E091C78259D06350440F759BD3") expect(message.first_plaintext_part.body.to_s).to include("C4D60F8833789C7CAA44496FD3FFA6613AB10ECE") expect(message.first_plaintext_part.body.to_s).to include("87E65ED2081AE3D16BE4F0A5EBDBE899251F2412") teardown_list_and_mailer(list) end context "with broken utf8 in key" do it "x-list-keys works" do list = create(:list) list.subscribe("schleuder@example.org", '59C71FB38AEE22E091C78259D06350440F759BD3', true) list.import_key(File.read('spec/fixtures/example_key.txt')) list.import_key(File.read("spec/fixtures/broken_utf8_uid_key.txt")) ENV['GNUPGHOME'] = list.listdir mail = Mail.new mail.to = list.request_address mail.from = list.admins.first.email gpg_opts = { encrypt: true, keys: {list.request_address => list.fingerprint}, sign: true, sign_as: list.admins.first.fingerprint } mail.gpg(gpg_opts) mail.body = "x-list-name: #{list.email}\nX-list-keys" mail.deliver encrypted_mail = Mail::TestMailer.deliveries.first Mail::TestMailer.deliveries.clear begin Schleuder::Runner.new().run(encrypted_mail.to_s, list.request_address) rescue SystemExit end raw = Mail::TestMailer.deliveries.first message = Mail.create_message_to_list(raw.to_s, list.request_address, list).setup expect(message.first_plaintext_part.body.to_s.lines.size).to eql(16) expect(message.first_plaintext_part.body.to_s).to include("59C71FB38AEE22E091C78259D06350440F759BD3") expect(message.first_plaintext_part.body.to_s).to include("3102B29989BEE703AE5ED62E1242F6E13D8EBE4A") teardown_list_and_mailer(list) end it "x-add-key with inline key-material" do list = create(:list, keywords_admin_notify: []) list.subscribe("schleuder@example.org", '59C71FB38AEE22E091C78259D06350440F759BD3', true) list_keys_num = list.keys.size ENV['GNUPGHOME'] = list.listdir mail = Mail.new mail.to = list.request_address mail.from = list.admins.first.email gpg_opts = { encrypt: true, keys: {list.request_address => list.fingerprint}, sign: true, sign_as: list.admins.first.fingerprint } mail.gpg(gpg_opts) keymaterial = File.read("spec/fixtures/broken_utf8_uid_key.txt") mail.body = "x-list-name: #{list.email}\nX-ADD-KEY:\n#{keymaterial}" mail.deliver encrypted_mail = Mail::TestMailer.deliveries.first Mail::TestMailer.deliveries.clear begin Schleuder::Runner.new().run(encrypted_mail.to_s, list.request_address) rescue SystemExit end raw = Mail::TestMailer.deliveries.first message = Mail.create_message_to_list(raw.to_s, list.request_address, list).setup expect(list.keys.size).to eql(list_keys_num + 1) expect(message.to).to eql(['schleuder@example.org']) expect(message.first_plaintext_part.body.to_s).to match(/This key was newly added:\n0x3102B29989BEE703AE5ED62E1242F6E13D8EBE4A info@buendnis-gegen-rechts.ch \d{4}-\d{2}-\d{2}\n/) teardown_list_and_mailer(list) end it "x-get-key with valid argument" do list = create(:list) list.subscribe("schleuder@example.org", '59C71FB38AEE22E091C78259D06350440F759BD3', true) list.import_key(File.read("spec/fixtures/broken_utf8_uid_key.txt")) ENV['GNUPGHOME'] = list.listdir mail = Mail.new mail.to = list.request_address mail.from = list.admins.first.email gpg_opts = { encrypt: true, keys: {list.request_address => list.fingerprint}, sign: true, sign_as: list.admins.first.fingerprint } mail.gpg(gpg_opts) mail.body = "x-list-name: #{list.email}\nX-GET-KEY: 0x3102B29989BEE703AE5ED62E1242F6E13D8EBE4A" mail.deliver encrypted_mail = Mail::TestMailer.deliveries.first Mail::TestMailer.deliveries.clear begin Schleuder::Runner.new().run(encrypted_mail.to_s, list.request_address) rescue SystemExit end raw = Mail::TestMailer.deliveries.first message = Mail.create_message_to_list(raw.to_s, list.request_address, list).setup expect(message.to_s).to match(/pub 1024D\/3102B29989BEE703AE5ED62E1242F6E13D8EBE4A \d{4}-\d{2}-\d{2}/) expect(message.to_s).to include("-----BEGIN PGP PUBLIC KEY") teardown_list_and_mailer(list) end end end schleuder-3.6.0/spec/schleuder/integration/protected_headers_spec.rb000066400000000000000000000116601401002544500257530ustar00rootroot00000000000000require "spec_helper" describe "protected subject" do it "is not leaked" do list = create(:list) list.subscribe("schleuder@example.org", '59C71FB38AEE22E091C78259D06350440F759BD3', true) mail = Mail.read("spec/fixtures/mails/protected-headers.eml") mail.deliver encrypted_mail = Mail::TestMailer.deliveries.first Mail::TestMailer.deliveries.clear begin Schleuder::Runner.new().run(encrypted_mail.to_s, list.email) rescue SystemExit end raw = Mail::TestMailer.deliveries.first expect(raw.subject).to eql('Encrypted Message') teardown_list_and_mailer(list) end it "is included in mime-headers" do list = create(:list) list.subscribe("schleuder@example.org", '59C71FB38AEE22E091C78259D06350440F759BD3', true) mail = Mail.read("spec/fixtures/mails/protected-headers.eml") mail.deliver encrypted_mail = Mail::TestMailer.deliveries.first Mail::TestMailer.deliveries.clear begin Schleuder::Runner.new().run(encrypted_mail.to_s, list.email) rescue SystemExit end raw = Mail::TestMailer.deliveries.first message = Mail.create_message_to_list(raw.to_s, list.request_address, list).setup expect(raw.to_s).not_to match('Re: the real subject') expect(message.subject).to eql("Re: the real subject") expect(message.content_type_parameters['protected-headers']).to eql("v1") teardown_list_and_mailer(list) end it "is included as mime-part in body" do list = create(:list) list.subscribe("schleuder@example.org", '59C71FB38AEE22E091C78259D06350440F759BD3', true) mail = Mail.read("spec/fixtures/mails/protected-headers.eml") mail.deliver encrypted_mail = Mail::TestMailer.deliveries.first Mail::TestMailer.deliveries.clear begin Schleuder::Runner.new().run(encrypted_mail.to_s, list.email) rescue SystemExit end raw = Mail::TestMailer.deliveries.first message = Mail.create_message_to_list(raw.to_s, list.request_address, list).setup expect(message.parts[1].body.to_s).to eql("Subject: Re: the real subject\n") teardown_list_and_mailer(list) end it "don't block request-messages" do list = create(:list, email: 'something@example.org') list.subscribe("schleuder@example.org", '59C71FB38AEE22E091C78259D06350440F759BD3', true) mail = Mail.read("spec/fixtures/mails/protected-headers-request.eml") mail.deliver encrypted_mail = Mail::TestMailer.deliveries.first Mail::TestMailer.deliveries.clear begin Schleuder::Runner.new().run(encrypted_mail.to_s, list.request_address) rescue SystemExit end raw = Mail::TestMailer.deliveries.first message = Mail.create_message_to_list(raw.to_s, list.request_address, list).setup expect(message.body.to_s).to include('59C71FB38AEE22E091C78259D06350440F759BD3') teardown_list_and_mailer(list) end it "works with mutt protected headers" do list = create(:list) list.subscribe("schleuder@example.org", '59C71FB38AEE22E091C78259D06350440F759BD3', true) mail = Mail.read("spec/fixtures/mutt_protected_headers.txt") mail.deliver encrypted_mail = Mail::TestMailer.deliveries.first Mail::TestMailer.deliveries.clear begin Schleuder::Runner.new().run(encrypted_mail.to_s, list.email) rescue SystemExit end raw = Mail::TestMailer.deliveries.first message = Mail.create_message_to_list(raw.to_s, list.request_address, list).setup expect(message.parts[1].body.to_s).to eql("Subject: x\n") expect(message.parts[2].body.to_s).to eql("test\n") teardown_list_and_mailer(list) end it "recognizes keywords in mails with protected headers and empty subject" do list = create(:list) list.subscribe("schleuder@example.org", '59C71FB38AEE22E091C78259D06350440F759BD3', true) ENV['GNUPGHOME'] = list.listdir mail = Mail.new mail.to = list.request_address mail.from = list.admins.first.email gpg_opts = { encrypt: true, keys: {list.request_address => list.fingerprint}, sign: true, sign_as: list.admins.first.fingerprint } mail.gpg(gpg_opts) mail.body = "x-list-name: #{list.email}\nx-list-keys" protected_headers = Mail::Part.new do body "Subject: protected" content_type "text/rfc822-headers; protected-headers=v1" end mail.add_part protected_headers mail.deliver encrypted_mail = Mail::TestMailer.deliveries.first Mail::TestMailer.deliveries.clear begin Schleuder::Runner.new().run(encrypted_mail.to_s, list.request_address) rescue SystemExit end raw = Mail::TestMailer.deliveries.first message = Mail.create_message_to_list(raw.to_s, list.request_address, list).setup expect(message.first_plaintext_part.body.to_s).to include("59C71FB38AEE22E091C78259D06350440F759BD3") expect(message.first_plaintext_part.body.to_s).to_not include("Your message didn't contain any keywords, thus there was nothing to do.") teardown_list_and_mailer(list) end end schleuder-3.6.0/spec/schleuder/integration/receive_bounce.rb000066400000000000000000000007111401002544500242250ustar00rootroot00000000000000require "spec_helper" describe "a bounce message is received" do it "from bounce example" do start_smtp_daemon list = create(:list) list.subscribe("admin@example.org", nil, true) message_path = 'spec/fixtures/mails/bounce.eml' error = run_schleuder(:work, list.email, message_path) mails = Dir.glob("#{smtp_daemon_outputdir}/mail-*") expect(error).to be_empty expect(mails.size).to eq 1 stop_smtp_daemon end end schleuder-3.6.0/spec/schleuder/integration/receive_different_charsets_spec.rb000066400000000000000000000013401401002544500276250ustar00rootroot00000000000000require "spec_helper" describe "user sends emails with different charsets" do Dir["spec/fixtures/mails/charset_mails/*.eml"].each do |f| it "works with #{File.basename(f,'.eml')}" do start_smtp_daemon list = create(:list) list.subscribe("admin@example.org", nil, true) # Clean any LANG from env as this is usually the case for MUAs # https://0xacab.org/schleuder/schleuder/issues/409 with_env(ENV.delete_if {|key, value| key =~ /LANG/ || key =~ /LC/ }) do error = run_schleuder(:work, list.email, f) mails = Dir.glob("#{smtp_daemon_outputdir}/mail-*") expect(error).to be_empty expect(mails.size).to eq 1 end stop_smtp_daemon end end end schleuder-3.6.0/spec/schleuder/integration/send_encrypted_spec.rb000066400000000000000000000011701401002544500252700ustar00rootroot00000000000000require "spec_helper" describe "user sends an encrypted message" do [ 'encrypted-inline', 'encrypted-mime', 'encrypted+signed-inline', 'encrypted+signed-mime', ].each do |t| it "from thunderbird being #{t}" do start_smtp_daemon list = create(:list) list.subscribe("admin@example.org", nil, true) message_path = "spec/fixtures/mails/#{t}/thunderbird.eml" error = run_schleuder(:work, list.email, message_path) mails = Dir.glob("#{smtp_daemon_outputdir}/mail-*") expect(error).to be_empty expect(mails.size).to eq 1 stop_smtp_daemon end end end schleuder-3.6.0/spec/schleuder/integration/send_plain_spec.rb000066400000000000000000000015341401002544500244020ustar00rootroot00000000000000require "spec_helper" describe "user sends a plain text message" do [ 'plain', 'signed-inline', 'signed-mime', ].each do |t| it "from thunderbird being #{t}" do list = create(:list, send_encrypted_only: false) list.subscribe("admin@example.org", nil, true) list.import_key(File.read('spec/fixtures/openpgpkey_52507B0163A8D9F0094FFE03B1A36F08069E55DE.asc')) mail = Mail.read("spec/fixtures/mails/#{t}/thunderbird.eml") error = nil begin Schleuder::Runner.new().run(mail.to_s, list.email) rescue SystemExit => exc error = exc end mails = Mail::TestMailer.deliveries expect(error).to be_nil expect(mails.size).to eq 1 content = mails.first.parts[0].parts[1].to_s expect(content).not_to include("-----BEGIN PGP SIGNATURE-----") end end end schleuder-3.6.0/spec/schleuder/runner_spec.rb000066400000000000000000000550261401002544500212610ustar00rootroot00000000000000require "spec_helper" describe Schleuder::Runner do describe "#run" do context "with a plain text message" do it "delivers the incoming message" do list = create(:list, send_encrypted_only: false) list.subscribe("admin@example.org", nil, true) mail = File.read("spec/fixtures/mails/plain/thunderbird.eml") error = Schleuder::Runner.new().run(mail, list.email) expect(Mail::TestMailer.deliveries.length).to eq 1 expect(error).to be_blank teardown_list_and_mailer(list) end it "has the correct headerlines" do list = create(:list, send_encrypted_only: false) list.subscribe("admin@example.org", nil, true) mail = File.read("spec/fixtures/mails/plain/thunderbird.eml") Schleuder::Runner.new().run(mail, list.email) message = Mail::TestMailer.deliveries.first expect(message.to).to eq ["admin@example.org"] expect(message.header.to_s.scan("admin@example.org").size).to eq 1 expect(message.from).to eq [list.email] teardown_list_and_mailer(list) end it "contains the specified pseudoheaders in the correct order" do list = create(:list, send_encrypted_only: false, headers_to_meta: ["from", "sig"]) list.subscribe("admin@example.org", nil, true) mail = File.read("spec/fixtures/mails/plain/thunderbird.eml") Schleuder::Runner.new().run(mail, list.email) message = Mail::TestMailer.deliveries.first content_part = message.parts.first separator = '------------------------------------------------------------------------------' pseudoheaders = "From: Nina Siessegger \nSig: Unsigned\n#{separator}\n" expect(content_part.parts.first.body).to include(pseudoheaders) expect(content_part.parts.first.body).not_to include('To:') expect(content_part.parts.first.body).not_to include('Enc:') expect(content_part.parts.first.body).not_to include('Date:') teardown_list_and_mailer(list) end it "doesn't have unwanted headerlines from the original message" do list = create(:list, send_encrypted_only: false) list.subscribe("admin@example.org", nil, true) mail = File.read("spec/fixtures/mails/plain/thunderbird.eml") Schleuder::Runner.new().run(mail, list.email) message = Mail::TestMailer.deliveries.first expect(message.to).to eq ["admin@example.org"] expect(message.header.to_s.scan("zeromail").size).to eq 0 expect(message.header.to_s.scan("nna.local").size).to eq 0 expect(message.header.to_s.scan("80.187.107.60").size).to eq 0 expect(message.header.to_s.scan("User-Agent:").size).to eq 0 teardown_list_and_mailer(list) end it "doesn't leak the Message-Id as configured" do list = create(:list, send_encrypted_only: false, keep_msgid: false) list.subscribe("admin@example.org", nil, true) mail = File.read("spec/fixtures/mails/plain/thunderbird.eml") Schleuder::Runner.new().run(mail, list.email) message = Mail::TestMailer.deliveries.first expect(message.header.to_s.scan("8db04406-e2ab-fd06-d4c5-c19b5765c52b@web.de").size).to eq 0 teardown_list_and_mailer(list) end it "does keep the Message-Id as configured" do list = create(:list, send_encrypted_only: false, keep_msgid: true) list.subscribe("admin@example.org", nil, true) mail = File.read("spec/fixtures/mails/plain/thunderbird.eml") Schleuder::Runner.new().run(mail, list.email) message = Mail::TestMailer.deliveries.first expect(message.header.to_s.scan("8db04406-e2ab-fd06-d4c5-c19b5765c52b@web.de").size).to eq 1 teardown_list_and_mailer(list) end it 'contains the Autocrypt header if include_autocrypt_header is set to true' do list = create( :list, send_encrypted_only: false, include_autocrypt_header: true, ) list.subscribe('admin@example.org', nil, true) mail = File.read('spec/fixtures/mails/plain/thunderbird.eml') Schleuder::Runner.new().run(mail, list.email) message = Mail::TestMailer.deliveries.first keydata = list.key_minimal_base64_encoded.gsub(/(.{78})/, '\1 ') expect(message.header['Autocrypt'].to_s).to eq("addr=#{list.email}; prefer-encrypt=mutual; keydata=#{keydata}") teardown_list_and_mailer(list) end it 'does not contain the Autocrypt header if include_autocrypt_header is set to false' do list = create( :list, send_encrypted_only: false, include_autocrypt_header: false, ) list.subscribe('admin@example.org', nil, true) mail = File.read('spec/fixtures/mails/plain/thunderbird.eml') Schleuder::Runner.new().run(mail, list.email) message = Mail::TestMailer.deliveries.first expect(message.header.to_s).to_not include('Autocrypt') teardown_list_and_mailer(list) end it "contains the list headers if include_list_headers is set to true" do list = create( :list, email: "superlist@example.org", send_encrypted_only: false, include_list_headers: true, ) list.subscribe("admin@example.org", nil, true) mail = File.read("spec/fixtures/mails/plain/thunderbird.eml") Schleuder::Runner.new().run(mail, list.email) message = Mail::TestMailer.deliveries.first expect(message.header["List-Id"].to_s).to eq "" expect(message.header["List-Owner"].to_s).to eq " (Use list's public key)" expect(message.header["List-Help"].to_s).to eq "" teardown_list_and_mailer(list) end it "contains the open pgp header if include_openpgp_header is set to true" do list = create( :list, send_encrypted_only: false, include_openpgp_header: true, ) list.subscribe("admin@example.org", nil, true) mail = File.read("spec/fixtures/mails/plain/thunderbird.eml") Schleuder::Runner.new().run(mail, list.email) message = Mail::TestMailer.deliveries.first expect(message.header["Openpgp"].to_s).to include list.fingerprint teardown_list_and_mailer(list) end it "does not deliver content if send_encrypted_only is set to true" do list = create(:list, send_encrypted_only: true) list.subscribe("admin@example.org", nil, true) mail = File.read("spec/fixtures/mails/plain/thunderbird.eml") Schleuder::Runner.new().run(mail, list.email) message = Mail::TestMailer.deliveries.first expect(message.body).to eq "" expect(message.parts.first.body.to_s).to include "You missed an email from "\ "#{list.email} because your subscription isn't associated with a "\ "(usable) OpenPGP key. Please fix this." teardown_list_and_mailer(list) end it "includes the internal_footer" do list = create( :list, send_encrypted_only: false, internal_footer: "-- \nfor our eyes only!" ) list.subscribe("admin@example.org", nil, true) mail = File.read("spec/fixtures/mails/plain/thunderbird.eml") Schleuder::Runner.new().run(mail, list.email) message = Mail::TestMailer.deliveries.first expect(message.parts.first.parts.last.body.to_s).to eql(list.internal_footer) teardown_list_and_mailer(list) end it "does not include the public_footer" do public_footer = "-- \nsomething public blabla" list = create( :list, send_encrypted_only: false, internal_footer: "-- \nfor our eyes only!", public_footer: public_footer ) list.subscribe("admin@example.org", nil, true) mail = File.read("spec/fixtures/mails/plain/thunderbird.eml") Schleuder::Runner.new().run(mail, list.email) message = Mail::TestMailer.deliveries.first expect(message.parts.first.to_s).not_to include(list.public_footer) teardown_list_and_mailer(list) end end context 'mails not encrypted to the list key' do it 'handles a mail which was encrypted to an absent key and returns DecryptionFailed error' do list = create( :list, send_encrypted_only: false ) list.subscribe("schleuder@example.org", nil, true) mail = File.read('spec/fixtures/mails/encrypted-to-absent-key.txt') result = Schleuder::Runner.new().run(mail, list.email) expect(result.class).to eql(Schleuder::Errors::DecryptionFailed) teardown_list_and_mailer(list) end it 'handles a mail which was encrypted to a passphrase and returns DecryptionFailed error' do list = create( :list, send_encrypted_only: false ) list.subscribe("schleuder@example.org", nil, true) mail = File.read('spec/fixtures/mails/encrypted-to-passphrase.txt') result = Schleuder::Runner.new().run(mail, list.email) expect(result.class).to eql(Schleuder::Errors::DecryptionFailed) teardown_list_and_mailer(list) end it 'handles a mail containing PGP-garbage and returns DecryptionFailed error' do list = create( :list, send_encrypted_only: false ) list.subscribe("schleuder@example.org", nil, true) mail = File.read('spec/fixtures/mails/containing-pgp-garbage.txt') result = Schleuder::Runner.new().run(mail, list.email) expect(result.class).to eql(Schleuder::Errors::DecryptionFailed) teardown_list_and_mailer(list) end end it "delivers a signed error message if a subscription's key is expired on a encrypted-only list" do list = create(:list, send_encrypted_only: true) list.subscribe("admin@example.org", nil, true, false) list.subscribe("expired@example.org", '98769E8A1091F36BD88403ECF71A3F8412D83889') key = File.read("spec/fixtures/expired_key.txt") list.import_key(key) mail = File.read("spec/fixtures/mails/plain/thunderbird.eml") Schleuder::Runner.new().run(mail, list.email) message = Mail::TestMailer.deliveries.first verified = message.verify signature_fingerprints = verified.signatures.map(&:fpr) expect(Mail::TestMailer.deliveries.size).to eq 1 expect(message.to).to include('expired@example.org') expect(message.to_s).to include("You missed an email from ") expect(signature_fingerprints).to eq([list.fingerprint]) teardown_list_and_mailer(list) end it "delivers a signed error message if a subscription's key is not available on a encrypted-only list" do list = create(:list, send_encrypted_only: true) list.subscribe("admin@example.org", 'AAAAAAAABBBBBBBBBCCCCCCCCCDDDDDDDDEEEEEE', true) mail = File.read("spec/fixtures/mails/plain/thunderbird.eml") Schleuder::Runner.new().run(mail, list.email) message = Mail::TestMailer.deliveries.first expect(message.to).to eq ['admin@example.org'] expect(message.to_s).to include("You missed an email from #{list.email} ") teardown_list_and_mailer(list) end it "injects pseudoheaders appropriately into an unsigned thunderbird-multipart/alternative-message" do list = create(:list, send_encrypted_only: false) list.subscribe("admin@example.org", nil, true) mail = File.read('spec/fixtures/mails/multipart-alternative/thunderbird-multi-alt-unsigned.eml') Schleuder::Runner.new().run(mail, list.email) message = Mail::TestMailer.deliveries.first content_part = message.parts.first expect(message.to).to eq ['admin@example.org'] expect(content_part.mime_type).to eql('multipart/mixed') expect(content_part.body).to be_blank expect(content_part.parts.size).to eql(2) expect(content_part.parts.first.mime_type).to eql('text/plain') expect(content_part.parts.first.body).to include('From: paz ') expect(content_part.parts.last.mime_type).to eql('multipart/alternative') teardown_list_and_mailer(list) end it "injects pseudoheaders appropriately into a signed multipart/alternative-message (thunderbird+enigmail-1.9) " do list = create(:list, send_encrypted_only: false) list.subscribe("admin@example.org", nil, true) mail = File.read('spec/fixtures/mails/multipart-alternative/thunderbird-multi-alt-signed.eml') Schleuder::Runner.new().run(mail, list.email) message = Mail::TestMailer.deliveries.first content_part = message.parts.first expect(message.to).to eq ['admin@example.org'] expect(content_part.mime_type).to eql('multipart/mixed') expect(content_part.body).to be_blank expect(content_part.parts.size).to eql(2) expect(content_part.parts.first.mime_type).to eql('text/plain') expect(content_part.parts.first.body).to include('From: paz ') expect(content_part.parts.last.mime_type).to eql('multipart/mixed') expect(content_part.parts.last.parts.size).to eql(1) expect(content_part.parts.last.parts.first.mime_type).to eql('multipart/alternative') teardown_list_and_mailer(list) end context "Quoted-Printable encoding" do it "is handled properly in cleartext emails" do list = create(:list, send_encrypted_only: false) list.subscribe("admin@example.org", nil, true) mail = File.read('spec/fixtures/mails/qp-encoding-clear.eml') Schleuder::Runner.new().run(mail, list.email) message = Mail::TestMailer.deliveries.first content_part = message.parts.first expect(content_part.parts.last.content_transfer_encoding).to eql('quoted-printable') expect(content_part.parts.last.body.encoded).to include('=3D86') expect(content_part.parts.last.body.encoded).not_to include('=86') teardown_list_and_mailer(list) end it "is handled properly in encrypted+signed emails" do list = create(:list, send_encrypted_only: false) list.subscribe("admin@example.org", "59C71FB38AEE22E091C78259D06350440F759BD3", true) mail = File.read('spec/fixtures/mails/qp-encoding-encrypted+signed.eml') Schleuder::Runner.new().run(mail, list.email) raw = Mail::TestMailer.deliveries.first message = Mail.create_message_to_list(raw.to_s, list.email, list).setup content_part = message.parts.last.first_plaintext_part expect(content_part.decoded).to include('bug=86') teardown_list_and_mailer(list) end it "is handled properly in encrypted emails" do list = create(:list, send_encrypted_only: false) list.subscribe("admin@example.org", nil, true) mail = File.read('spec/fixtures/mails/qp-encoding-encrypted.eml') Schleuder::Runner.new().run(mail, list.email) message = Mail::TestMailer.deliveries.first content_part = message.parts.first expect(content_part.parts.last.content_transfer_encoding).to eql('quoted-printable') expect(content_part.parts.last.body.encoded).to include('=3D86') expect(content_part.parts.last.body.encoded).not_to include('=86') teardown_list_and_mailer(list) end end it 'does not throw an error on emails with large first mime-part' do list = create(:list) list.subscribe("schleuder@example.org", '59C71FB38AEE22E091C78259D06350440F759BD3', true) ENV['GNUPGHOME'] = list.listdir mail = Mail.new mail.to = list.request_address mail.from = list.admins.first.email gpg_opts = { encrypt: true, keys: {list.request_address => list.fingerprint}, sign: true, sign_as: list.admins.first.fingerprint } mail.gpg(gpg_opts) mail.body = File.read('spec/fixtures/mails/big_first_mime_part.txt') mail.deliver message = Mail::TestMailer.deliveries.first Mail::TestMailer.deliveries.clear output = process_mail(message.to_s, list.email) expect(output).to be nil teardown_list_and_mailer(list) end it 'does not throw an error on emails that contain other gpg keywords' do list = create(:list) list.subscribe("schleuder@example.org", '59C71FB38AEE22E091C78259D06350440F759BD3', true) ENV['GNUPGHOME'] = list.listdir mail = Mail.new mail.to = list.request_address mail.from = list.admins.first.email gpg_opts = { encrypt: true, keys: {list.request_address => list.fingerprint}, sign: true, sign_as: list.admins.first.fingerprint } mail.gpg(gpg_opts) mail.body = File.read('spec/fixtures/mails/mail_with_pgp_boundaries_in_body.txt') mail.deliver message = Mail::TestMailer.deliveries.first Mail::TestMailer.deliveries.clear output = process_mail(message.to_s, list.email) expect(output).to be nil teardown_list_and_mailer(list) end it 'does not throw an error on emails with an attached pgp key as application/octet-stream' do list = create(:list) list.subscribe("schleuder@example.org", '59C71FB38AEE22E091C78259D06350440F759BD3', true) ENV['GNUPGHOME'] = list.listdir mail = Mail.new mail.to = list.request_address mail.from = list.admins.first.email gpg_opts = { encrypt: true, keys: {list.request_address => list.fingerprint}, sign: true, sign_as: list.admins.first.fingerprint } mail.gpg(gpg_opts) mail.body = 'See attachment' mail.attachments['251F2412.asc'] = { :content_type => '"application/octet-stream"; name="251F2412.asc"', :content_transfer_encoding => '7bit', :content => File.read('spec/fixtures/bla_foo_key.txt') } mail.deliver message = Mail::TestMailer.deliveries.first Mail::TestMailer.deliveries.clear output = process_mail(message.to_s, list.email) expect(output).to be nil teardown_list_and_mailer(list) end it 'does not throw an error on encrypted but unsigned emails that contain a forwarded encrypted email' do list = create(:list) list.subscribe("schleuder@example.org", '59C71FB38AEE22E091C78259D06350440F759BD3', true) ENV['GNUPGHOME'] = list.listdir mail = Mail.new mail.to = list.request_address mail.from = list.admins.first.email gpg_opts = { encrypt: true, keys: {list.request_address => list.fingerprint}, sign: false, } mail.gpg(gpg_opts) mail.body = "Hi\n\nI'll forward you this email, have a look at it!\n\n#{File.read('spec/fixtures/mails/encrypted-mime/thunderbird.eml')}" mail.deliver message = Mail::TestMailer.deliveries.first Mail::TestMailer.deliveries.clear output = process_mail(message.to_s, list.email) expect(output).to be nil teardown_list_and_mailer(list) end it 'does not throw an error on emails with broken utf-8' do list = create(:list, send_encrypted_only: false) list.subscribe("admin@example.org", nil, true) mail = File.read('spec/fixtures/mails/broken_utf8_charset.eml') # From mail 2.7.0 this is handled correctly # See #334 for background if Gem::Version.new(Mail::VERSION.version) < Gem::Version.new('2.7.0') expect{ Schleuder::Runner.new().run(mail, list.email) }.to raise_error(ArgumentError) else Schleuder::Runner.new().run(mail, list.email) message = Mail::TestMailer.deliveries.first output = process_mail(message.to_s, list.email) expect(output).to be nil end teardown_list_and_mailer(list) end end context 'after keyword parsing' do it 'falls back to default charset per RFC if none is set' do list = create(:list, send_encrypted_only: false) list.subscribe("admin@example.org", "59C71FB38AEE22E091C78259D06350440F759BD3", true) # manually build a specific mail structure that comes without a charset mail = Mail.new mail.from = "admin@example.org" mail.to = list.request_address ENV['GNUPGHOME'] = list.listdir cipher_data = GPGME::Data.new GPGME::Ctx.new({armor: true}) do |ctx| ctx.add_signer(*GPGME::Key.find(:secret, "59C71FB38AEE22E091C78259D06350440F759BD3", :sign)) ctx.encrypt_sign( GPGME::Key.find(:public,list.fingerprint, :encrypt), GPGME::Data.new("Content-Type: text/plain\n\nNur ein test\n"), cipher_data, 0 ) cipher_data.seek(0) end mail.content_type "multipart/encrypted; boundary=\"#{mail.boundary}\"; protocol=\"application/pgp-encrypted\"" ver_part = Mail::Part.new do body "Version: 1" content_type "application/pgp-encrypted" end mail.add_part ver_part enc_part = Mail::Part.new do body cipher_data.to_s content_type "application/octet-stream" end mail.add_part enc_part output = process_mail(mail.to_s, list.email) expect(output).to be nil teardown_list_and_mailer(list) end it 'falling back works also with non-ascii content' do list = create(:list, send_encrypted_only: false) list.subscribe("admin@example.org", "59C71FB38AEE22E091C78259D06350440F759BD3", true) # manually build a specific mail structure that comes without a charset mail = Mail.new mail.from = "admin@example.org" mail.to = list.request_address ENV['GNUPGHOME'] = list.listdir cipher_data = GPGME::Data.new GPGME::Ctx.new({armor: true}) do |ctx| ctx.add_signer(*GPGME::Key.find(:secret, "59C71FB38AEE22E091C78259D06350440F759BD3", :sign)) ctx.encrypt_sign( GPGME::Key.find(:public,list.fingerprint, :encrypt), GPGME::Data.new("Content-Type: text/plain\n\nNür ein test\n"), cipher_data, 0 ) cipher_data.seek(0) end mail.content_type "multipart/encrypted; boundary=\"#{mail.boundary}\"; protocol=\"application/pgp-encrypted\"" ver_part = Mail::Part.new do body "Version: 1" content_type "application/pgp-encrypted" end mail.add_part ver_part enc_part = Mail::Part.new do body cipher_data.to_s content_type "application/octet-stream" end mail.add_part enc_part output = process_mail(mail.to_s, list.email) expect(output).to be nil teardown_list_and_mailer(list) end end end schleuder-3.6.0/spec/schleuder/unit/000077500000000000000000000000001401002544500173605ustar00rootroot00000000000000schleuder-3.6.0/spec/schleuder/unit/conf_spec.rb000066400000000000000000000017111401002544500216440ustar00rootroot00000000000000require "spec_helper" describe Schleuder::Conf do it "reads ERB code in config files" do # Suppress warnings about already defined constants # if using "load" further below verbose_orig = $VERBOSE $VERBOSE = nil # Define constants val_old = "val_old" # Check if env var is set if not ENV["SCHLEUDER_DB_PATH"].nil? val_old = ENV["SCHLEUDER_DB_PATH"] end # Set env var, reload the config and check whether the correct value # is returned val_test = "SCHLEUDER_ERB_TEST" ENV["SCHLEUDER_DB_PATH"] = val_test load "schleuder/conf.rb" expect(Schleuder::Conf.database["database"]).to eql(val_test) # Reset the env var ENV["SCHLEUDER_DB_PATH"] = nil # Set the env var to the original value if val_old != "val_old" ENV["SCHLEUDER_DB_PATH"] = val_old end load "schleuder/conf.rb" # Set verbose level to original value $VERBOSE = $verbose_orig end end schleuder-3.6.0/spec/schleuder/unit/filters_runner_spec.rb000066400000000000000000000126731401002544500237710ustar00rootroot00000000000000require "spec_helper" module Schleuder::Filters def self.dummy(list,mail) nil end def self.stop(list,mail) nil end end describe Schleuder::Filters::Runner do let(:list) do # setup the list with an admin that can be notified list = create(:list, send_encrypted_only: false) list.subscribe("schleuder@example.org", nil, true) list end let(:pre_filters) { Schleuder::Filters::Runner.new(list,'pre') } let(:post_filters){ Schleuder::Filters::Runner.new(list,'post') } it { expect(pre_filters).to respond_to :run } context '#run' do it 'runs the filters' do mail = Mail.new expect(Schleuder::Filters).to receive(:dummy).once expect(Schleuder::Filters).to_not receive(:stop) expect(pre_filters).to receive(:filters).and_return(['dummy']) expect(pre_filters.run(mail)).to be_nil end it 'stops on a StandardError and returns error' do mail = Mail.new error = StandardError.new expect(Schleuder::Filters).to_not receive(:dummy) expect(Schleuder::Filters).to receive(:stop).once { error } expect(pre_filters).to receive(:filters).and_return(['stop','dummy']) expect(pre_filters.run(mail)).to eql(error) expect(Mail::TestMailer.deliveries.first).to be_nil end it 'stops on a StandardError and will notify admins' do mail = Mail.new error = StandardError.new pre_filters.list.bounces_drop_all = true expect(Schleuder::Filters).to_not receive(:dummy) expect(Schleuder::Filters).to receive(:stop).once { error } expect(pre_filters).to receive(:filters).and_return(['stop','dummy']) expect(pre_filters.run(mail)).to be_nil expect(Mail::TestMailer.deliveries.first).to_not be_nil end it 'stops on a StandardError and will notify on headers match' do mail = Mail.new error = StandardError.new mail['X-SPAM-FLAG'] = 'TRUE' expect(Schleuder::Filters).to_not receive(:dummy) expect(Schleuder::Filters).to receive(:stop).once { error } expect(pre_filters).to receive(:filters).and_return(['stop','dummy']) expect(pre_filters.run(mail)).to be_nil expect(Mail::TestMailer.deliveries.first).to_not be_nil end end context 'loading filters' do it 'loads filters from built-in filters_dir sorts them' do Schleuder::Conf.instance.config['filters_dir'] = File.join(Dir.pwd,'spec/fixtures/no_filters') expect(pre_filters.filters).to eq [ 'forward_bounce_to_admins', 'forward_all_incoming_to_admins', 'send_key', 'fix_exchange_messages', 'strip_html_from_alternative' ] expect(post_filters.filters).to eq [ 'request', 'max_message_size', 'forward_to_owner', 'receive_admin_only', 'receive_authenticated_only', 'receive_signed_only', 'receive_encrypted_only', 'receive_from_subscribed_emailaddresses_only', 'strip_html_from_alternative_if_keywords_present' ] end it 'loads custom filters from filters_dir and sorts them in, ignores filter not following convention' do Schleuder::Conf.instance.config['filters_dir'] = File.join(Dir.pwd,'spec/fixtures/filters') expect(pre_filters.filters).to eq [ 'forward_bounce_to_admins', 'forward_all_incoming_to_admins', 'example', 'send_key', 'fix_exchange_messages', 'strip_html_from_alternative' ] expect(post_filters.filters).to eq [ 'request', 'max_message_size', 'forward_to_owner', 'receive_admin_only', 'receive_authenticated_only', 'receive_signed_only', 'receive_encrypted_only', 'post_example', 'receive_from_subscribed_emailaddresses_only', 'strip_html_from_alternative_if_keywords_present' ] end it 'loads custom filters from filters_dir and sorts them in with missing dir' do Schleuder::Conf.instance.config['filters_dir'] = File.join(Dir.pwd,'spec/fixtures/filters_without_pre') expect(pre_filters.filters).to eq [ 'forward_bounce_to_admins', 'forward_all_incoming_to_admins', 'send_key', 'fix_exchange_messages', 'strip_html_from_alternative' ] expect(post_filters.filters).to eq [ 'post_example', 'request', 'max_message_size', 'forward_to_owner', 'receive_admin_only', 'receive_authenticated_only', 'receive_signed_only', 'receive_encrypted_only', 'receive_from_subscribed_emailaddresses_only', 'strip_html_from_alternative_if_keywords_present' ] end it 'loads custom filters from filters_dir even with non-2-digit priority' do Schleuder::Conf.instance.config['filters_dir'] = File.join(Dir.pwd,'spec/fixtures/more_filters') expect(pre_filters.filters).to eq [ 'early_example', 'forward_bounce_to_admins', 'forward_all_incoming_to_admins', 'example', 'send_key', 'fix_exchange_messages', 'strip_html_from_alternative', 'late_example' ] expect(post_filters.filters).to eq [ 'request', 'max_message_size', 'forward_to_owner', 'receive_admin_only', 'receive_authenticated_only', 'receive_signed_only', 'receive_encrypted_only', 'receive_from_subscribed_emailaddresses_only', 'strip_html_from_alternative_if_keywords_present', ] end end end schleuder-3.6.0/spec/schleuder/unit/filters_spec.rb000066400000000000000000000127651401002544500224020ustar00rootroot00000000000000require "spec_helper" describe Schleuder::Filters do before do # Make sure we have the filters loaded, as they will be loaded lazily within the code. list = create(:list) Schleuder::Filters::Runner.new(list, 'pre').filters Schleuder::Filters::Runner.new(list, 'post').filters end context '.fix_exchange_messages' do it "fixes pgp/mime-messages that were mangled by Exchange" do message = Mail.read("spec/fixtures/mails/exchange.eml") Schleuder::Filters.fix_exchange_messages(nil, message) expect(message[:content_type].content_type).to eql("multipart/encrypted") end it "works with a text/plain message" do message = Mail.read("spec/fixtures/mails/exchange_no_parts.eml") Schleuder::Filters.fix_exchange_messages(nil, message) expect(message[:content_type].content_type).to eql("text/plain") end end context '.strip_html_from_alternative' do it "strips HTML-part from multipart/alternative-message that contains ascii-armored PGP-data" do list = create(:list) mail = Mail.new mail.list = list mail.to = list.email mail.from = 'outside@example.org' content = encrypt_string(list, "blabla") mail.text_part = content mail.html_part = "

#{content}

" mail.subject = "test" Schleuder::Filters.strip_html_from_alternative(list, mail) expect(mail[:content_type].content_type).to eql("multipart/mixed") expect(mail.parts.size).to be(1) expect(mail.parts.first[:content_type].content_type).to eql("text/plain") expect(mail.dynamic_pseudoheaders).to include("Note: This message included an alternating HTML-part that contained\n PGP-data. The HTML-part was removed to enable parsing the message more\n properly.") end it "does NOT strip HTML-part from multipart/alternative-message that does NOT contain ascii-armored PGP-data" do mail = Mail.new mail.to = 'schleuder@example.org' mail.from = 'outside@example.org' content = "blabla" mail.text_part = content mail.html_part = "

#{content}

" mail.subject = "test" Schleuder::Filters.strip_html_from_alternative(nil, mail) expect(mail[:content_type].content_type).to eql("multipart/alternative") expect(mail.parts.size).to be(2) expect(mail.parts.first[:content_type].content_type).to eql("text/plain") expect(mail.parts.last[:content_type].content_type).to eql("text/html") expect(mail.dynamic_pseudoheaders).not_to include("Note: This message included an alternating HTML-part that contained PGP-data. The HTML-part was removed to enable parsing the message more properly.") end it "does not choke on nor change a message without Content-Type-header" do mail = Mail.new mail.to = 'schleuder@example.org' mail.from = 'outside@example.org' mail.body = "blabla" mail.subject = "test" Schleuder::Filters.strip_html_from_alternative(nil, mail) expect(mail[:content_type]).to be_nil expect(mail.parts.size).to be(0) expect(mail.dynamic_pseudoheaders).not_to include("Note: This message included an alternating HTML-part that contained PGP-data. The HTML-part was removed to enable parsing the message more properly.") end end context '.strip_html_from_alternative_if_keywords_present' do it 'strips HTML-part from multipart/alternative-message that contains keywords' do list = create(:list) mail = Mail.new mail.list = list mail.to = list.email mail.from = 'outside@example.org' mail.text_part = content = 'x-resend: someone@example.org\n\nblabla' mail.html_part = '

x-resend: someone@example.org

blabla

' mail.subject = 'test' mail.to_s Schleuder::Filters.strip_html_from_alternative_if_keywords_present(list, mail) expect(mail[:content_type].content_type).to eql('multipart/mixed') expect(mail.parts.size).to be(1) expect(mail.parts.first[:content_type].content_type).to eql('text/plain') expect(mail.dynamic_pseudoheaders).to include("Note: This message included keywords and an alternating HTML-part. The\n HTML-part was removed to prevent the disclosure of these keywords to third\n parties.") end it 'does NOT strip HTML-part from multipart/alternative-message that does NOT contain keywords' do list = create(:list) mail = Mail.new mail.list = list mail.to = 'schleuder@example.org' mail.from = 'outside@example.org' mail.text_part = content = 'Hello someone@example.org,\n\nblabla' mail.html_part = '

Hello someone@example.org,

blabla

' mail.subject = 'test' Schleuder::Filters.strip_html_from_alternative_if_keywords_present(list, mail) expect(mail[:content_type].content_type).to eql('multipart/alternative') expect(mail.parts.size).to be(2) expect(mail.parts.first[:content_type].content_type).to eql('text/plain') expect(mail.parts.last[:content_type].content_type).to eql('text/html') expect(mail.dynamic_pseudoheaders).to be_blank end it 'does not choke on nor change a message without Content-Type-header' do mail = Mail.new mail.to = 'schleuder@example.org' mail.from = 'outside@example.org' mail.body = 'blabla' mail.subject = 'test' Schleuder::Filters.strip_html_from_alternative_if_keywords_present(nil, mail) expect(mail[:content_type]).to be_nil expect(mail.parts.size).to be(0) expect(mail.dynamic_pseudoheaders).to be_blank end end end schleuder-3.6.0/spec/schleuder/unit/gpgme_ctx.rb000066400000000000000000000207511401002544500216670ustar00rootroot00000000000000require "spec_helper" describe GPGME::Ctx do it "#keyimport" do list = create(:list) keymaterial = File.read('spec/fixtures/example_key.txt') expect(list.gpg.keys.map(&:fingerprint)).not_to include('C4D60F8833789C7CAA44496FD3FFA6613AB10ECE') expect { list.gpg.keyimport(keymaterial) }.to change{ list.gpg.keys.size }.by 1 expect(list.gpg.keys.map(&:fingerprint)).to include('C4D60F8833789C7CAA44496FD3FFA6613AB10ECE') end it "#keyimport with unusable data" do list = create(:list) keymaterial = "blabla" expect(list.gpg.keys.map(&:fingerprint)).not_to include('C4D60F8833789C7CAA44496FD3FFA6613AB10ECE') expect { list.gpg.keyimport(keymaterial) }.to change{ list.gpg.keys.size }.by 0 expect(list.gpg.keys.map(&:fingerprint)).not_to include('C4D60F8833789C7CAA44496FD3FFA6613AB10ECE') end it "#find_keys with prefixed fingerprint" do list = create(:list) list.import_key(File.read("spec/fixtures/example_key.txt")) keys = list.gpg.find_keys('0x59C71FB38AEE22E091C78259D06350440F759BD3') expect(keys.size).to eql(1) end it "#find_keys with un-prefixed fingerprint" do list = create(:list) list.import_key(File.read("spec/fixtures/example_key.txt")) keys = list.gpg.find_keys('59C71FB38AEE22E091C78259D06350440F759BD3') expect(keys.size).to eql(1) end it "#find_keys with bracketed email-address" do list = create(:list) list.import_key(File.read("spec/fixtures/example_key.txt")) keys = list.gpg.find_keys('schleuder ') expect(keys.size).to eql(1) end it "#find_keys with bracketed wrong email-address" do list = create(:list) list.import_key(File.read("spec/fixtures/example_key.txt")) keys = list.gpg.find_keys('blabla ') expect(keys.size).to eql(0) end it "#find_keys with un-bracketed email-address" do list = create(:list) list.import_key(File.read("spec/fixtures/example_key.txt")) keys = list.gpg.find_keys('schleuder@example.org') expect(keys.size).to eql(1) end it "#find_keys with un-bracketed wrong email-address" do list = create(:list) list.import_key(File.read("spec/fixtures/example_key.txt")) keys = list.gpg.find_keys('blabla@example.org') expect(keys.size).to eql(0) end it "#find_keys with correctly marked sub-string" do list = create(:list) list.import_key(File.read("spec/fixtures/example_key.txt")) keys = list.gpg.find_keys('@schleuder') expect(keys.size).to eql(2) end it "#find_keys with correctly marked narrower sub-string" do list = create(:list) list.import_key(File.read("spec/fixtures/example_key.txt")) keys = list.gpg.find_keys('@schleuder@') expect(keys.size).to eql(1) end it "#find_keys with un-marked sub-string" do list = create(:list) list.import_key(File.read("spec/fixtures/example_key.txt")) keys = list.gpg.find_keys('schleuder') expect(keys.size).to eql(2) end it "#find_keys without argument" do list = create(:list) list.import_key(File.read("spec/fixtures/example_key.txt")) keys = list.gpg.find_keys() expect(keys.size).to eql(2) end it "#clean_and_classify_input with prefixed fingerprint" do list = create(:list) kind, input = list.gpg.clean_and_classify_input('0x59C71FB38AEE22E091C78259D06350440F759BD3') expect(kind).to eql(:fingerprint) expect(input).to eql('0x59C71FB38AEE22E091C78259D06350440F759BD3') end it "#clean_and_classify_input with un-prefixed fingerprint" do list = create(:list) kind, input = list.gpg.clean_and_classify_input('59C71FB38AEE22E091C78259D06350440F759BD3') expect(kind).to eql(:fingerprint) expect(input).to eql('0x59C71FB38AEE22E091C78259D06350440F759BD3') end it "#clean_and_classify_input with bracketed email-address" do list = create(:list) kind, input = list.gpg.clean_and_classify_input('bla ') expect(kind).to eql(:email) expect(input).to eql('') end it "#clean_and_classify_input with un-bracketed email-address" do list = create(:list) kind, input = list.gpg.clean_and_classify_input('bla@foo') expect(kind).to eql(:email) expect(input).to eql('') end it "#clean_and_classify_input with URL" do list = create(:list) kind, input = list.gpg.clean_and_classify_input('http://example.org/foo') expect(kind).to eql(:url) expect(input).to eql('http://example.org/foo') end it "#clean_and_classify_input with some string" do list = create(:list) kind, input = list.gpg.clean_and_classify_input('lala') expect(kind).to eql(nil) expect(input).to eql('lala') end it "#gpgcli returns correct data types" do list = create(:list) err, out, exitcode = list.gpg.class.gpgcli('--list-keys') expect(err.class).to eql(Array) expect(out.class).to eql(Array) expect(exitcode.class).to eql(Integer) end it "#gpgcli_expect returns correct data types" do list = create(:list) err, out, exitcode = list.gpg.class.gpgcli_expect('--list-keys') { nil } expect(err.class).to eql(Array) expect(out.class).to eql(NilClass) expect(exitcode.class).to eql(Integer) end context "#keyserver_arg" do it "returns keyserver-args if a keyserver is configured" do list = create(:list) keyserver_args = list.gpg.send(:keyserver_arg) expect(keyserver_args).to eql("--keyserver #{Conf.keyserver}") end it "returns a blank string if the keyserver-option is set to a blank value" do oldval = Conf.instance.config['keyserver'] Conf.instance.config['keyserver'] = '' list = create(:list) keyserver_args = list.gpg.send(:keyserver_arg) expect(keyserver_args).to eql("") Conf.instance.config['keyserver'] = oldval end end context '#refresh_keys' do it 'updates keys from the keyserver' do list = create(:list) list.subscribe("admin@example.org", nil, true) list.import_key(File.read("spec/fixtures/expired_key.txt")) list.import_key(File.read("spec/fixtures/olduid_key.txt")) res = '' with_sks_mock do res = list.gpg.refresh_keys(list.keys) end expect(res).to match(/This key was updated \(new signatures\):\n0x98769E8A1091F36BD88403ECF71A3F8412D83889 bla@foo \d{4}-\d{2}-\d{2} \[expired: \d{4}-\d{2}-\d{2}\]/) expect(res).to match(/This key was updated \(new user-IDs and new signatures\):\n0x6EE51D78FD0B33DE65CCF69D2104E20E20889F66 new@example.org \d{4}-\d{2}-\d{2}/) if GPGME::Ctx.sufficient_gpg_version?('2.1') dirmngr_pid = `pgrep -a dirmngr | grep #{list.listdir}`.split(' ',2).first # no error occurred expect(dirmngr_pid).not_to be_nil end end it 'reports errors from refreshing keys' do list = create(:list) list.subscribe("admin@example.org", nil, true) list.import_key(File.read("spec/fixtures/expired_key.txt")) res = list.gpg.refresh_keys(list.keys) expect(res).to include("Refreshing all keys from the keyring of list #{list.email} resulted in this") if GPGME::Ctx.sufficient_gpg_version?('2.1') expect(mail.to_s).to include("keyserver refresh failed: No keyserver available") dirmngr_pid = `pgrep -a dirmngr | grep #{list.listdir}`.split(' ',2).first expect(dirmngr_pid).not_to be_nil else # The wording differs slightly among versions. expect(mail.to_s).to match(/gpgkeys: .* error .* connect/) end end it 'does not import non-self-signatures if gpg >= 2.1.15; or else sends a warning' do list = create(:list) list.delete_key('87E65ED2081AE3D16BE4F0A5EBDBE899251F2412') list.subscribe('admin@example.org', nil, true) list.import_key(File.read('spec/fixtures/bla_foo_key.txt')) res = '' with_sks_mock do res = list.gpg.refresh_keys(list.keys) end # GPGME apparently does not show signatures correctly in some cases, so we better use gpgcli. signature_output = list.gpg.class.gpgcli(['--list-sigs', '87E65ED2081AE3D16BE4F0A5EBDBE899251F2412'])[1].grep(/0F759BD3.*schleuder@example.org/) if GPGME::Ctx.sufficient_gpg_version?('2.1.15') expect(res).to be_empty expect(signature_output).to be_empty else message = Mail::TestMailer.deliveries.first expect(message.to).to eql([Conf.superadmin]) expect(message.subject).to eql('Schleuder installation problem') expect(res).not_to be_empty expect(signature_output).not_to be_empty end end end end schleuder-3.6.0/spec/schleuder/unit/gpgme_key.rb000066400000000000000000000061511401002544500216570ustar00rootroot00000000000000require "spec_helper" describe GPGME::Key do describe '#minimal' do it 'returns a minimal key' do list = create(:list) list.import_key(File.read('spec/fixtures/schleuder_at_example_public_key.txt')) expect(list.key.minimal()).to eq(File.read('spec/fixtures/schleuder_at_example_public_key_minimal.gpg', mode: 'rb')) end end describe "#oneline" do it "displays the expected basic attributes" do list = create(:list) key = list.key expect(key.oneline).to match(/0x59C71FB38AEE22E091C78259D06350440F759BD3 schleuder@example.org \d{4}-\d{2}-\d{2}/) end it "displays the expected attributes for an expiring key" do list = create(:list) list.import_key(File.read("spec/fixtures/expiring_key.txt")) key = list.key("421FBF7190640136788593CD9EE9BE5929CACC20") expect(key.oneline).to match(/0x421FBF7190640136788593CD9EE9BE5929CACC20 expiringkey@example.org \d{4}-\d{2}-\d{2} \[expires: \d{4}-\d{2}-\d{2}\]/) end it "displays the expected attributes for an expired key" do list = create(:list) list.import_key(File.read("spec/fixtures/expired_key.txt")) key = list.key("98769E8A1091F36BD88403ECF71A3F8412D83889") expect(key.oneline).to match(/0x98769E8A1091F36BD88403ECF71A3F8412D83889 bla@foo \d{4}-\d{2}-\d{2} \[expired: \d{4}-\d{2}-\d{2}\]/) end it "displays the expected attributes for a revoked key" do list = create(:list) list.import_key(File.read("spec/fixtures/revoked_key.txt")) key = list.key("7E783CDE6D1EFE6D2409739C098AC83A4C0028E9") expect(key.oneline).to match(/0x7E783CDE6D1EFE6D2409739C098AC83A4C0028E9 paz@nadir.org \d{4}-\d{2}-\d{2} \[revoked\]/) end # gpgme.rb doesn't report missing encryption-capability properly yet. it "displays the expected attributes for a key that's not capable of encryption" do list = create(:list) list.import_key(File.read("spec/fixtures/signonly_key.txt")) key = list.key("B1CD8BB15C2673C6BFD8FA4B70B2CF29E01AD53E") expect(key.oneline).to match(/0xB1CD8BB15C2673C6BFD8FA4B70B2CF29E01AD53E signonly@example.org \d{4}-\d{2}-\d{2} \[not capable of encryption\]/) end end describe '.valid_fingerprint?' do context 'valid fingerprints' do ['59C71FB38AEE22E091C78259D06350440F759BD3', '0x59C71FB38AEE22E091C78259D06350440F759BD3', '59C71FB38AEE22E091C78259D0635044', '0x59C71FB38AEE22E091C78259D0635044', ].each do |fp| it "accepts #{fp} as a valid fingerprint" do expect(described_class.valid_fingerprint?(fp)).to be_truthy end end end context 'invalid fingerprints' do ['Z9C71FB38AEE22E091C78259D06350440F759BD3', '59C71FB38AEE22E091C78259D06350440F759BD3A', '59C71FB38AEE22E091C78259D06350440F759BD', '0x59C71FB38AEE22E091C78259D06350440F759B', 'Z9C71FB38AEE22E091C78259D0635044', 'Z9C71FB38AEE22E091C78259D0635044', ].each do |fp| it "rejects #{fp} as an invalid fingerprint" do expect(described_class.valid_fingerprint?(fp)).to be_falsey end end end end end schleuder-3.6.0/spec/schleuder/unit/list_builder_spec.rb000066400000000000000000000077111401002544500234060ustar00rootroot00000000000000require "spec_helper" describe Schleuder::ListBuilder do it "creates a new, valid list" do listname = "list-#{rand}@example.org" adminaddress = 'schleuder2@example.org' adminkey = File.read('spec/fixtures/example_key.txt') list, messages = ListBuilder.new({email: listname, fingerprint: nil}, adminaddress, nil, adminkey).run expect(list).to be_an_instance_of Schleuder::List expect(list).to be_valid expect(messages).to be_blank end it "returns an error-message if given an invalid email-address" do listname = "list-#{rand}" adminaddress = 'schleuder2@example.org' adminkey = File.read('spec/fixtures/example_key.txt') list, messages = ListBuilder.new({email: listname, fingerprint: nil}, adminaddress, nil, adminkey).run expect(list).to be_nil expect(messages).to be_an_instance_of Hash expect(messages.keys).to eq ['email'] expect(messages.values).to be_present end it "returns an error-message if given an invalid email-address with a space" do listname = "list #{rand}@example.com" adminaddress = 'schleuder2@example.org' adminkey = File.read('spec/fixtures/example_key.txt') list, messages = ListBuilder.new({email: listname, fingerprint: nil}, adminaddress, nil, adminkey).run expect(list).to be_nil expect(messages).to be_an_instance_of Hash expect(messages.keys).to eq ['email'] expect(messages.values).to be_present end it "creates a listdir for the list" do listname = "list-#{rand}@example.org" adminaddress = 'schleuder2@example.org' adminkey = File.read('spec/fixtures/example_key.txt') list, _ = ListBuilder.new({email: listname, fingerprint: nil}, adminaddress, nil, adminkey).run expect(File.directory?(list.listdir)).to be true end it "creates a list-key with all required UIDs" do listname = "list-#{rand}@example.org" adminaddress = 'schleuder2@example.org' adminkey = File.read('spec/fixtures/example_key.txt') list, _ = ListBuilder.new({email: listname, fingerprint: nil}, adminaddress, nil, adminkey).run uids = list.key.uids.map(&:email) expect(uids).to include(list.email) expect(uids).to include(list.request_address) expect(uids).to include(list.owner_address) end it "subscribes the adminaddress and imports the adminkey" do listname = "list-#{rand}@example.org" adminaddress = 'schleuder2@example.org' adminkey = File.read('spec/fixtures/example_key.txt') list, _ = ListBuilder.new({email: listname, fingerprint: nil}, adminaddress, nil, adminkey).run subscription_emails = list.subscriptions.map(&:email) keys_fingerprints = list.keys.map(&:fingerprint) expect(subscription_emails).to eq [adminaddress] expect(keys_fingerprints).to include("C4D60F8833789C7CAA44496FD3FFA6613AB10ECE") end it "subscribes the adminaddress and respects the given adminfingerprint" do listname = "list-#{rand}@example.org" adminaddress = 'schleuder2@example.org' list, _ = ListBuilder.new({email: listname, fingerprint: nil}, adminaddress, "59C71FB38AEE22E091C78259D06350440F759BD3").run subscription_emails = list.subscriptions.map(&:email) admin_subscription = list.admins.first expect(subscription_emails).to eq [adminaddress] expect(admin_subscription.fingerprint).to eql("59C71FB38AEE22E091C78259D06350440F759BD3") end it "subscribes the adminaddress and ignores the adminfingerprint if an adminkey was given" do listname = "list-#{rand}@example.org" adminaddress = 'schleuder2@example.org' adminkey = File.read('spec/fixtures/example_key.txt') list, _ = ListBuilder.new({email: listname, fingerprint: nil}, adminaddress, "59C71FB38AEE22E091C78259D06350440F759BD3", adminkey).run subscription_emails = list.subscriptions.map(&:email) subscription_fingerprints = list.subscriptions.map(&:fingerprint) expect(subscription_emails).to eq [adminaddress] expect(subscription_fingerprints).to eq ["C4D60F8833789C7CAA44496FD3FFA6613AB10ECE"] end end schleuder-3.6.0/spec/schleuder/unit/list_spec.rb000066400000000000000000001164451401002544500217050ustar00rootroot00000000000000require "spec_helper" describe Schleuder::List do BOOLEAN_LIST_ATTRIBUTES = [ :send_encrypted_only, :receive_encrypted_only, :receive_signed_only, :receive_authenticated_only, :receive_from_subscribed_emailaddresses_only, :receive_admin_only, :keep_msgid, :bounces_drop_all, :bounces_notify_admins, :deliver_selfsent, :include_list_headers, :include_list_headers, :include_openpgp_header, :forward_all_incoming_to_admins, :set_reply_to_to_sender, :munge_from, ].freeze it "has a valid factory" do list = create(:list_with_one_subscription) expect(list).to be_valid end it { is_expected.to respond_to :subscriptions } it { is_expected.to respond_to :email } it { is_expected.to respond_to :fingerprint } it { is_expected.to respond_to :log_level } it { is_expected.to respond_to :subject_prefix } it { is_expected.to respond_to :subject_prefix_in } it { is_expected.to respond_to :subject_prefix_out } it { is_expected.to respond_to :openpgp_header_preference } it { is_expected.to respond_to :internal_footer } it { is_expected.to respond_to :public_footer } it { is_expected.to respond_to :headers_to_meta } it { is_expected.to respond_to :bounces_drop_on_headers } it { is_expected.to respond_to :keywords_admin_only } it { is_expected.to respond_to :keywords_admin_notify } it { is_expected.to respond_to :send_encrypted_only } it { is_expected.to respond_to :receive_encrypted_only } it { is_expected.to respond_to :receive_signed_only } it { is_expected.to respond_to :receive_authenticated_only } it { is_expected.to respond_to :receive_from_subscribed_emailaddresses_only } it { is_expected.to respond_to :receive_admin_only } it { is_expected.to respond_to :keep_msgid } it { is_expected.to respond_to :bounces_drop_all } it { is_expected.to respond_to :bounces_notify_admins } it { is_expected.to respond_to :deliver_selfsent } it { is_expected.to respond_to :include_list_headers } it { is_expected.to respond_to :include_openpgp_header } it { is_expected.to respond_to :max_message_size_kb } it { is_expected.to respond_to :language } it { is_expected.to respond_to :forward_all_incoming_to_admins } it { is_expected.to respond_to :logfiles_to_keep } it { is_expected.to respond_to :set_reply_to_to_sender } it { is_expected.to respond_to :munge_from } it "is invalid when email is nil" do # Don't use factory here because we'd run into List.listdir expecting email to not be nil. list = Schleuder::List.new(email: nil) expect(list).not_to be_valid expect(list.errors.messages[:email]).to include("can't be blank") end it "is invalid when email is blank" do list = build(:list, email: "") expect(list).not_to be_valid expect(list.errors.messages[:email]).to include("can't be blank") end it "is invalid when email does not contain an @" do list = build(:list, email: "fooatbar.org") expect(list).not_to be_valid expect(list.errors.messages[:email]).to include("is not a valid email address") end it "is invalid when email contains a space" do list = build(:list, email: "foo bu@bar.org") expect(list).not_to be_valid expect(list.errors.messages[:email]).to include("is not a valid email address") end it "is invalid when fingerprint is blank" do list = build(:list, fingerprint: "") expect(list).not_to be_valid expect(list.errors.messages[:fingerprint]).to include("can't be blank") end it "is invalid when fingerprint is nil" do list = build(:list, fingerprint: nil) expect(list).not_to be_valid expect(list.errors.messages[:fingerprint]).to include("can't be blank") end it "is invalid when fingerprint contains invalid characters" do list = build(:list, fingerprint: "&$$$$67923AAA") expect(list).not_to be_valid expect(list.errors.messages[:fingerprint]).to include("is not a valid OpenPGP-fingerprint") end BOOLEAN_LIST_ATTRIBUTES.each do |list_attribute| it "is invalid if #{list_attribute} is nil" do list = build(:list) list[list_attribute] = nil expect(list).not_to be_valid expect(list.errors.messages[list_attribute]).to include("must be true or false") end it "is invalid if #{list_attribute} is blank" do list = build(:list) list[list_attribute] = "" expect(list).not_to be_valid expect(list.errors.messages[list_attribute]).to include("must be true or false") end end [:headers_to_meta, :keywords_admin_only, :keywords_admin_notify].each do |list_attribute| it "is invalid if #{list_attribute} contains special characters" do list = build(:list) list[list_attribute] =["$from", "to", "date", "cc"] expect(list).not_to be_valid expect(list.errors.messages[list_attribute]).to include("contains invalid characters") end it "is valid if #{list_attribute} does not contain special characters" do list = build(:list) list[list_attribute] = ["foobar"] expect(list).to be_valid end end it "is invalid if bounces_drop_on_headers contains special characters" do list = build(:list, bounces_drop_on_headers: {"$" => "%"}) expect(list).not_to be_valid expect(list.errors.messages[:bounces_drop_on_headers]).to include("contains invalid characters") end [:subject_prefix, :subject_prefix_in, :subject_prefix_out].each do |list_attribute| it "is invalid if #{list_attribute} contains a linebreak" do list = build(:list) list[list_attribute] = "Foo\nbar" expect(list).not_to be_valid expect(list.errors.messages[list_attribute]).to include("must not include line-breaks") end it "is valid if #{list_attribute} is nil" do list = build(:list) list[list_attribute] = nil expect(list).to be_valid end end it "is invalid if openpgp_header_preference is foobar" do list = build(:list, openpgp_header_preference: "foobar") expect(list).not_to be_valid expect(list.errors.messages[:openpgp_header_preference]).to include("must be one of: sign, encrypt, signencrypt, unprotected, none") end [:max_message_size_kb, :logfiles_to_keep].each do |list_attribute| it "is invalid if #{list_attribute} is 0" do list = build(:list) list[list_attribute] = 0 expect(list).not_to be_valid expect(list.errors.messages[list_attribute]).to include("must be a number greater than zero") end end it "is invalid if log_level is foobar" do list = build(:list, log_level: "foobar") expect(list).not_to be_valid expect(list.errors.messages[:log_level]).to include("must be one of: debug, info, warn, error") end it "is invalid if language is jp" do list = build(:list, language: "jp") expect(list).not_to be_valid expect(list.errors.messages[:language]).to include("must be one of: en, de") end it "is invalid if internal_footer includes a non-printable character" do list = build(:list, internal_footer: "\a") expect(list).not_to be_valid expect(list.errors.messages[:internal_footer]).to include("includes non-printable characters") end it "is invalid if public_footer includes a non-printable character" do list = build(:list, public_footer: "\a") expect(list).not_to be_valid expect(list.errors.messages[:public_footer]).to include("includes non-printable characters") end describe ".configurable_attributes" do it "returns an array that contains the configurable attributes" do expect(Schleuder::List.configurable_attributes).to eq [ :bounces_drop_all, :bounces_drop_on_headers, :bounces_notify_admins, :deliver_selfsent, :forward_all_incoming_to_admins, :headers_to_meta, :include_list_headers, :include_openpgp_header, :internal_footer, :keep_msgid, :keywords_admin_notify, :keywords_admin_only, :language, :log_level, :logfiles_to_keep, :max_message_size_kb, :munge_from, :openpgp_header_preference, :public_footer, :receive_admin_only, :receive_authenticated_only, :receive_encrypted_only, :receive_from_subscribed_emailaddresses_only, :receive_signed_only, :send_encrypted_only, :set_reply_to_to_sender, :subject_prefix, :subject_prefix_in, :subject_prefix_out, ] end it "does not contain the attributes email and fingerprint" do expect(Schleuder::List.configurable_attributes).to_not include(:email) expect(Schleuder::List.configurable_attributes).to_not include(:fingerprint) end end describe "#fingerprint" do it "transforms the fingerprint to upper case" do list = Schleuder::List.new(email: "example@example.org", fingerprint: "c4d60f8833789c7caa44496fd3ffa6613ab10ece") expect(list.fingerprint).to eq("C4D60F8833789C7CAA44496FD3FFA6613AB10ECE") end it "removes whitespaces and 0x from the fingerprint" do fingerprint = "0x 99 991 1000 10" list = build(:list, fingerprint: fingerprint) expect(list.fingerprint).to eq "99991100010" end end describe "#logfile" do it "returns the logfile path" do list = create(:list, email: "foo@bar.org") expect(list.logfile).to eq File.join(Schleuder::Conf.listlogs_dir, "bar.org/foo/list.log") end end describe "#logger" do it "calls the ListLogger" do list = create(:list) expect(Listlogger).to receive(:new).with(list) list.logger end end describe "#to_s" do it "returns the email" do list = create(:list, email: "foo@bar.org") expect(list.email).to eq "foo@bar.org" end end describe "#admins" do it "returns subscriptions of admin users" do list = create(:list) admin_subscription = create( :subscription, email: "admin@foo.org", admin: true, list_id: list.id, ) _user_subscription = create( :subscription, email: "user@foo.org", admin: false, list_id: list.id, ) expect(list.admins).to eq [admin_subscription] end end describe "#key" do it "returns the key with the fingerprint of the list" do list = create( :list, fingerprint: "59C7 1FB3 8AEE 22E0 91C7 8259 D063 5044 0F75 9BD3" ) expect(list.key.fingerprint()).to eq "59C71FB38AEE22E091C78259D06350440F759BD3" end end describe "#secret_key" do it "returns the secret key with the fingerprint of the list" do list = create( :list, fingerprint: "59C71FB38AEE22E091C78259D06350440F759BD3" ) expect(list.secret_key.secret?).to eq true expect(list.secret_key.fingerprint).to eq "59C71FB38AEE22E091C78259D06350440F759BD3" end end describe "#keys" do it "it returns an array with the keys of the list" do list = create(:list) expect(list.keys).to be_kind_of Array expect(list.keys.length).to eq 1 end it "returns an array of keys matching the given fingerprint" do list = create( :list, fingerprint: "59C71FB38AEE22E091C78259D06350440F759BD3" ) expect(list.keys).to be_kind_of Array expect(list.keys.first.fingerprint).to eq "59C71FB38AEE22E091C78259D06350440F759BD3" end it "returns an array with the keys matching the given email address" do list = create(:list, email: "schleuder@example.org") expect(list.keys("schleuder@example.org").length).to eq 1 expect( list.keys("schleuder@example.org").first.fingerprint ).to eq "59C71FB38AEE22E091C78259D06350440F759BD3" end it "returns an array with the keys matching the given bracketed email address" do list = create(:list, email: "schleuder@example.org") expect( list.keys("bla ").first.fingerprint ).to eq "59C71FB38AEE22E091C78259D06350440F759BD3" end end describe "#import_key" do it "imports a given key" do list = create(:list) key = File.read("spec/fixtures/example_key.txt") expect { list.import_key(key) }.to change { list.keys.count }.by(1) list.delete_key("C4D60F8833789C7CAA44496FD3FFA6613AB10ECE") end end describe "#delete_key" do it "deletes the key with the given fingerprint" do list = create(:list) key = File.read("spec/fixtures/example_key.txt") list.import_key(key) expect do list.delete_key("C4D60F8833789C7CAA44496FD3FFA6613AB10ECE") end.to change { list.keys.count }.by(-1) end it "returns false if no key with the fingerprint was found" do list = create(:list) expect(list.delete_key("A4C60C8833789C7CAA44496FD3FFA6611AB10CEC")).to eq false end end describe "#export_key" do it "exports the key with the fingerprint of the list if no argument is given" do list = create(:list, email: "schleuder@example.org") expected_public_key = File.read("spec/fixtures/schleuder_at_example_public_key.txt") # Get rid of the first, opening line, so we don't compare against optional comments in the output, etc. expected_public_key = expected_public_key.split("\n").slice(1..-1).join("\n") expect(list.export_key()).to include expected_public_key end end describe '#key_minimal_base64_encoded' do it 'returns the key with the fingerprint of the list if no argument is given in an Autocrypt-compatible format' do list = create(:list) expect(list.key_minimal_base64_encoded()).to eq(File.read('spec/fixtures/schleuder_at_example_public_key_minimal_base64.txt')) end it 'does not return the key with the fingerprint in an Autocrypt-compatible format if the argument given does not correspond to a key' do list = create(:list) expect(list.key_minimal_base64_encoded('this fpr does not exist')).to be(false) end end it "exports the key with the given fingerprint" do list = create(:list, email: "schleuder@example.org") expected_public_key = File.read("spec/fixtures/schleuder_at_example_public_key.txt") # Get rid of the first, opening line, so we don't compare against optional comments in the output, etc. expected_public_key = expected_public_key.split("\n").slice(1..-1).join("\n") expect( list.export_key("59C71FB38AEE22E091C78259D06350440F759BD3") ).to include expected_public_key end describe "#check_keys" do it "adds a message if a key expires in two weeks or less" do list = create(:list) key = double("key") generation_time = Time.now - 1.year expiry_time = Time.now + 7.days allow_any_instance_of(GPGME::Key).to receive(:subkeys).and_return(key) allow(key).to receive(:first).and_return(key) allow(key).to receive(:timestamp).and_return(generation_time) allow(key).to receive(:expires?).and_return(true) allow(key).to receive(:expired?).and_return(false) allow(key).to receive(:expired).and_return(false) allow(key).to receive(:any?).and_return(false) allow(key).to receive(:expires).and_return(expiry_time) allow(key).to receive(:fingerprint).and_return("59C71FB38AEE22E091C78259D06350440F759BD3") datefmt = "%Y-%m-%d" generation_date = generation_time.strftime(datefmt) expiry_date = expiry_time.strftime(datefmt) expect(list.check_keys).to eq "This key expires in 6 days:\n0x59C71FB38AEE22E091C78259D06350440F759BD3 schleuder@example.org #{generation_date} [expires: #{expiry_date}]\n\n" end it "adds a message if a key is revoked" do list = create(:list) allow_any_instance_of(GPGME::Key).to receive(:trust).and_return(:revoked) expect(list.check_keys).to match(/This key is revoked:\n0x59C71FB38AEE22E091C78259D06350440F759BD3 schleuder@example.org \d{4}-\d{2}-\d{2} \[revoked\]\n\n/) end it "adds a message if a key is disabled" do list = create(:list) allow_any_instance_of(GPGME::Key).to receive(:trust).and_return(:disabled) expect(list.check_keys).to match(/This key is disabled:\n0x59C71FB38AEE22E091C78259D06350440F759BD3 schleuder@example.org \d{4}-\d{2}-\d{2} \[disabled\]\n\n/) end it "adds a message if a key is invalid" do list = create(:list) allow_any_instance_of(GPGME::Key).to receive(:trust).and_return(:invalid) expect(list.check_keys).to match(/This key is invalid:\n0x59C71FB38AEE22E091C78259D06350440F759BD3 schleuder@example.org \d{4}-\d{2}-\d{2} \[invalid\]\n\n/) end end describe ".by_recipient" do it "returns the list for a given address" do list = create(:list, email: "list@example.org") expect(Schleuder::List.by_recipient("list-owner@example.org")).to eq list end end describe "#sendkey_address" do it "adds the sendkey keyword to the email address" do list = create(:list, email: "list@example.org") expect(list.sendkey_address).to eq "list-sendkey@example.org" end end describe "#request_address" do it "adds the request keyword to the email address" do list = create(:list, email: "list@example.org") expect(list.request_address).to eq "list-request@example.org" end end describe "#owner_address" do it "adds the owner keyword to the email address" do list = create(:list, email: "list@example.org") expect(list.owner_address).to eq "list-owner@example.org" end end describe "#bounce_address" do it "adds the bounce keyword to the email address" do list = create(:list, email: "list@example.org") expect(list.bounce_address).to eq "list-bounce@example.org" end end describe "#gpg" do it "returns an instance of GPGME::Ctx" do list = create(:list) expect(list.gpg).to be_an_instance_of GPGME::Ctx end it "sets the GNUPGHOME environment variable to the listdir" do list = create(:list) list.gpg expect(ENV["GNUPGHOME"]).to eq list.listdir end end context '#fetch_keys' do it 'fetches one key by fingerprint' do list = create(:list) list.subscribe("admin@example.org", nil, true) output = '' with_sks_mock(list.listdir) do output = list.fetch_keys('98769E8A1091F36BD88403ECF71A3F8412D83889') end expect(output).to match(/This key was fetched \(new key\):\n0x98769E8A1091F36BD88403ECF71A3F8412D83889 bla@foo \d{4}-\d{2}-\d{2} \[expired: \d{4}-\d{2}-\d{2}\]/) teardown_list_and_mailer(list) end it 'fetches one key by URL' do list = create(:list) list.subscribe("admin@example.org", nil, true) output = '' with_sks_mock(list.listdir) do output = list.fetch_keys('http://localhost:9999/keys/example.asc') end expect(output).to match(/This key was fetched \(new key\):\n0x98769E8A1091F36BD88403ECF71A3F8412D83889 bla@foo \d{4}-\d{2}-\d{2} \[expired: \d{4}-\d{2}-\d{2}\]/) teardown_list_and_mailer(list) end it 'fetches one key by email address' do list = create(:list) list.subscribe("admin@example.org", nil, true) output = '' with_sks_mock(list.listdir) do output = list.fetch_keys('admin@example.org') end expect(output).to match(/This key was fetched \(new key\):\n0x98769E8A1091F36BD88403ECF71A3F8412D83889 bla@foo \d{4}-\d{2}-\d{2} \[expired: \d{4}-\d{2}-\d{2}\]/) teardown_list_and_mailer(list) end it 'does not import non-self-signatures if gpg >= 2.1.15; or else sends a warning' do list = create(:list) list.delete_key('87E65ED2081AE3D16BE4F0A5EBDBE899251F2412') list.subscribe('admin@example.org', nil, true) output = '' with_sks_mock(list.listdir) do output = list.fetch_keys('87E65ED2081AE3D16BE4F0A5EBDBE899251F2412') end # GPGME apparently does not show signatures correctly in some cases, so we better use gpgcli. signature_output = list.gpg.class.gpgcli(['--list-sigs', '87E65ED2081AE3D16BE4F0A5EBDBE899251F2412'])[1].grep(/0F759BD3.*schleuder@example.org/) expect(output).to include("This key was fetched (new key):\n0x87E65ED2081AE3D16BE4F0A5EBDBE899251F2412 bla@foo") if GPGME::Ctx.gpg_knows_import_filter? expect(signature_output).to be_empty else message = Mail::TestMailer.deliveries.first expect(message.to).to eql([Conf.superadmin]) expect(message.subject).to eql('Schleuder installation problem') expect(signature_output).not_to be_empty end teardown_list_and_mailer(list) end end describe "send_list_key_to_subscriptions" do it "sends its key to all subscriptions" do list = create(:list, send_encrypted_only: false) list.subscribe("admin@example.org", nil, true) list.send_list_key_to_subscriptions raw = Mail::TestMailer.deliveries.first expect(raw.parts.first.parts.first.body.to_s).to eql("Find the key for this address attached.") expect(raw.parts.first.parts.last.body.to_s).to include("4096R/59C71FB38AEE22E091C78259D06350440F759BD3") expect(raw.parts.first.parts.last.body.to_s).to include("-----BEGIN PGP PUBLIC KEY BLOCK-----") end end describe "#subscribe" do it "subscribes and ignores nil-values for admin and delivery_enabled" do list = create(:list) sub, _ = list.subscribe("admin@example.org", nil, nil, nil) expect(sub.admin?).to be(false) expect(sub.delivery_enabled?).to be(true) end it "subscribes and sets the fingerprint from key material that contains exactly one key" do list = create(:list) key_material = File.read("spec/fixtures/example_key.txt") sub, msgs = list.subscribe("admin@example.org", "", true, true, key_material) expect(msgs).to be(nil) expect(sub.fingerprint).to eql("C4D60F8833789C7CAA44496FD3FFA6613AB10ECE") expect(list.subscriptions.size).to be(1) expect(list.subscriptions.first.fingerprint).to eql("C4D60F8833789C7CAA44496FD3FFA6613AB10ECE") expect(list.keys.size).to be(2) expect(list.keys.map(&:fingerprint)).to eql(["59C71FB38AEE22E091C78259D06350440F759BD3", "C4D60F8833789C7CAA44496FD3FFA6613AB10ECE"]) end it "subscribes and does not set the fingerprint from key material containing multiple keys" do list = create(:list) key_material = File.read("spec/fixtures/example_key.txt") key_material << File.read("spec/fixtures/olduid_key.txt") sub, msgs = list.subscribe("admin@example.org", "", true, true, key_material) expect(msgs).to eql("The given key material contained more than one key, could not determine which fingerprint to use. Please set it manually!") expect(sub.fingerprint).to be_blank expect(list.subscriptions.size).to be(1) expect(list.subscriptions.first.fingerprint).to be_blank expect(list.keys.size).to be(3) expect(list.keys.map(&:fingerprint)).to eql(["59C71FB38AEE22E091C78259D06350440F759BD3", "C4D60F8833789C7CAA44496FD3FFA6613AB10ECE", "6EE51D78FD0B33DE65CCF69D2104E20E20889F66"]) end it "subscribes and does not set the fingerprint from key material containing no keys" do list = create(:list) key_material = "blabla" sub, msgs = list.subscribe("admin@example.org", "", true, true, key_material) expect(msgs).to eql("The given key material did not contain any keys!") expect(sub.fingerprint).to be_blank expect(list.subscriptions.size).to be(1) expect(list.subscriptions.first.fingerprint).to be_blank expect(list.keys.size).to be(1) expect(list.keys.map(&:fingerprint)).to eql(["59C71FB38AEE22E091C78259D06350440F759BD3"]) end it "subscribes and ignores a given fingerprint if key material is given, too" do list = create(:list) key_material = "blabla" sub, msgs = list.subscribe("admin@example.org", "C4D60F8833789C7CAA44496FD3FFA6613AB10ECE", true, true, key_material) expect(msgs).to eql("The given key material did not contain any keys!") expect(sub.fingerprint).to be_blank expect(list.subscriptions.size).to be(1) expect(list.subscriptions.first.fingerprint).to be_blank expect(list.keys.size).to be(1) expect(list.keys.map(&:fingerprint)).to eql(["59C71FB38AEE22E091C78259D06350440F759BD3"]) end end describe "#send_to_subscriptions" do it "sends the message to all subscribers" do list = create(:list, send_encrypted_only: false) sub, msgs = list.subscribe("admin@example.org", nil, true) sub, msgs = list.subscribe("user1@example.org") sub, msgs = list.subscribe("user2@example.org") mail = Mail.new mail.to = list.email mail.from = 'something@localhost' mail.subject = 'Something' mail.body = "Some content" Schleuder::Runner.new().run(mail.to_s, list.email) messages = Mail::TestMailer.deliveries recipients = messages.map { |m| m.to.first }.sort expect(messages.size).to be(3) expect(recipients).to eql(['admin@example.org', 'user1@example.org', 'user2@example.org']) expect(messages[0].parts.first.parts.last.body.to_s).to eql("Some content") expect(messages[0].subject).to eql("Something") expect(messages[1].parts.first.parts.last.body.to_s).to eql("Some content") expect(messages[1].subject).to eql("Something") expect(messages[2].parts.first.parts.last.body.to_s).to eql("Some content") expect(messages[2].subject).to eql("Something") teardown_list_and_mailer(list) end it "sends the message to all subscribers, in the clear if one's key is unusable, if send_encrypted_only is false" do list = create(:list, send_encrypted_only: false) sub, msgs = list.subscribe("admin@example.org", nil, true) key_material = File.read("spec/fixtures/expired_key.txt") sub, msgs = list.subscribe("user1@example.org", nil, false, true, key_material) sub, msgs = list.subscribe("user2@example.org") mail = Mail.new mail.to = list.email mail.from = 'something@localhost' mail.subject = 'Something' mail.body = "Some content" Schleuder::Runner.new().run(mail.to_s, list.email) messages = Mail::TestMailer.deliveries recipients = messages.map { |m| m.to.first }.sort expect(messages.size).to be(3) expect(recipients).to eql(['admin@example.org', 'user1@example.org', 'user2@example.org']) expect(messages[0].parts.first.parts.last.body.to_s).to eql("Some content") expect(messages[0].subject).to eql("Something") expect(messages[1].parts.first.parts.last.body.to_s).to eql("Some content") expect(messages[1].subject).to eql("Something") expect(messages[2].parts.first.parts.last.body.to_s).to eql("Some content") expect(messages[2].subject).to eql("Something") teardown_list_and_mailer(list) end it "sends the message only to subscribers with available keys if send_encrypted_only is true, and a notification to the other subscribers" do list = create(:list, send_encrypted_only: true) sub, msgs = list.subscribe("admin@example.org", '59C71FB38AEE22E091C78259D06350440F759BD3', true) sub, msgs = list.subscribe("user1@example.org") sub, msgs = list.subscribe("user2@example.org", '59C71FB38AEE22E091C78259D06350440F759BD3') mail = Mail.new mail.to = list.email mail.from = 'something@localhost' mail.subject = 'Something' mail.body = "Some content" Schleuder::Runner.new().run(mail.to_s, list.email) messages = Mail::TestMailer.deliveries recipients = messages.map { |m| m.to.first }.sort expect(messages.size).to be(3) expect(recipients).to eql(['admin@example.org', 'user1@example.org', 'user2@example.org']) expect(messages[0].parts.last.body.to_s).to include("-----BEGIN PGP MESSAGE-----") expect(messages[0].subject).to eql("Something") expect(messages[1].parts.first.body.to_s).to include("You missed an email") expect(messages[1].subject).to eql("Notice") expect(messages[2].parts.last.body.to_s).to include("-----BEGIN PGP MESSAGE-----") expect(messages[2].subject).to eql("Something") teardown_list_and_mailer(list) end it "sends the message only to subscribers with usable keys if send_encrypted_only is true, and a notification to the other subscribers" do list = create(:list, send_encrypted_only: true) key_material = File.read("spec/fixtures/partially_expired_key.txt") sub, msgs = list.subscribe("admin@example.org", nil, true, true, key_material) key_material = File.read("spec/fixtures/expired_key.txt") sub, msgs = list.subscribe("user1@example.org", nil, false, true, key_material) sub, msgs = list.subscribe("user2@example.org", '59C71FB38AEE22E091C78259D06350440F759BD3') mail = Mail.new mail.to = list.email mail.from = 'something@localhost' mail.subject = 'Something' mail.body = "Some content" Schleuder::Runner.new().run(mail.to_s, list.email) messages = Mail::TestMailer.deliveries recipients = messages.map { |m| m.to.first }.sort expect(messages.size).to be(3) expect(recipients).to eql(['admin@example.org', 'user1@example.org', 'user2@example.org']) expect(messages[0].parts.first.body.to_s).to include("You missed an email") expect(messages[0].subject).to eql("Notice") expect(messages[1].parts.first.body.to_s).to include("You missed an email") expect(messages[1].subject).to eql("Notice") expect(messages[2].parts.last.body.to_s).to include("-----BEGIN PGP MESSAGE-----") expect(messages[2].subject).to eql("Something") teardown_list_and_mailer(list) end it "sends the message to all subscribers including the sender, if deliver_selfsent is true and the mail is correctly signed" do list = create(:list, send_encrypted_only: false, deliver_selfsent: true) key_material = File.read("spec/fixtures/default_list_key.txt") sub, msgs = list.subscribe("admin@example.org", nil, true, true, key_material) key_material = File.read("spec/fixtures/example_key.txt") sub, msgs = list.subscribe("user1@example.org", nil, false, true, key_material) mail = Mail.new mail.to = list.email mail.from = 'user1@example.org' mail.subject = 'Something' mail.body = "Some content" gpg_opts = { sign: true, sign_as: '59C71FB38AEE22E091C78259D06350440F759BD3' } mail.gpg(gpg_opts) mail.deliver signed_mail = Mail::TestMailer.deliveries.first Mail::TestMailer.deliveries.clear Schleuder::Runner.new().run(signed_mail.to_s, list.email) messages = Mail::TestMailer.deliveries recipients = messages.map { |m| m.to.first }.sort expect(list.deliver_selfsent).to be(true) expect(messages.size).to be(2) expect(recipients).to eql(['admin@example.org', 'user1@example.org']) expect(messages[0].parts.last.body.to_s).to include("-----BEGIN PGP MESSAGE-----") expect(messages[0].subject).to eql("Something") expect(messages[1].parts.last.body.to_s).to include("-----BEGIN PGP MESSAGE-----") expect(messages[1].subject).to eql("Something") teardown_list_and_mailer(list) end it "sends the message to all subscribers but not the sender, if deliver_selfsent is false and the mail is correctly signed" do list = create(:list, send_encrypted_only: false, deliver_selfsent: false) key_material = File.read("spec/fixtures/default_list_key.txt") sub, msgs = list.subscribe("admin@example.org", nil, true, true, key_material) key_material = File.read("spec/fixtures/example_key.txt") sub, msgs = list.subscribe("user1@example.org", nil, false, true, key_material) mail = Mail.new mail.to = list.email mail.from = 'admin@example.org' mail.subject = 'Something' mail.body = "Some content" gpg_opts = { sign: true, sign_as: '59C71FB38AEE22E091C78259D06350440F759BD3' } mail.gpg(gpg_opts) mail.deliver signed_mail = Mail::TestMailer.deliveries.first Mail::TestMailer.deliveries.clear Schleuder::Runner.new().run(signed_mail.to_s, list.email) messages = Mail::TestMailer.deliveries recipients = messages.map { |m| m.to.first }.sort expect(list.deliver_selfsent).to be(false) expect(messages.size).to be(1) expect(recipients).to eql(['user1@example.org']) expect(messages[0].parts.last.body.to_s).to include("-----BEGIN PGP MESSAGE-----") expect(messages[0].subject).to eql("Something") teardown_list_and_mailer(list) end it "sends the message to all subscribers including the sender, if deliver_selfsent is false but the mail is not correctly signed" do list = create(:list, send_encrypted_only: false, deliver_selfsent: false) key_material = File.read("spec/fixtures/default_list_key.txt") sub, msgs = list.subscribe("admin@example.org", nil, true, true, key_material) key_material = File.read("spec/fixtures/example_key.txt") sub, msgs = list.subscribe("user1@example.org", nil, false, true, key_material) mail = Mail.new mail.to = list.email mail.from = 'admin@example.org' mail.subject = 'Something' mail.body = "Some content" Schleuder::Runner.new().run(mail.to_s, list.email) messages = Mail::TestMailer.deliveries recipients = messages.map { |m| m.to.first }.sort expect(list.deliver_selfsent).to be(false) expect(messages.size).to be(2) expect(recipients).to eql(['admin@example.org', 'user1@example.org']) expect(messages[0].parts.last.body.to_s).to include("-----BEGIN PGP MESSAGE-----") expect(messages[0].subject).to eql("Something") teardown_list_and_mailer(list) end end describe "#set_reply_to_to_sender" do it "is disabled by default" do list = create(:list) expect(list.set_reply_to_to_sender).to be(false) teardown_list_and_mailer(list) end it "does not set reply_to mail address when disabled" do list = create(:list, set_reply_to_to_sender: false) key_material = File.read("spec/fixtures/default_list_key.txt") sub, msgs = list.subscribe("admin@example.org", nil, true, true, key_material) sub, msgs = list.subscribe("user1@example.org", nil, false, true, key_material) sub, msgs = list.subscribe("user2@example.org", nil, false, true, key_material) mail = Mail.new mail.to = list.email mail.from = "something@localhost" mail.subject = "Something" mail.body = "Some content" Schleuder::Runner.new().run(mail.to_s, list.email) messages = Mail::TestMailer.deliveries recipients = messages.map { |m| m.to.first }.sort expect(messages.size).to be(3) expect(recipients).to eql(['admin@example.org', 'user1@example.org', 'user2@example.org']) expect(messages[0].from).to eql([list.email]) expect(messages[0].reply_to).to be_nil expect(messages[1].from).to eql([list.email]) expect(messages[1].reply_to).to be_nil expect(messages[2].from).to eql([list.email]) expect(messages[2].reply_to).to be_nil teardown_list_and_mailer(list) end it "sets reply-to to senders from-address when enabled" do list = create(:list, set_reply_to_to_sender: true) key_material = File.read("spec/fixtures/default_list_key.txt") sub, msgs = list.subscribe("admin@example.org", nil, true, true, key_material) sub, msgs = list.subscribe("user1@example.org", nil, false, true, key_material) sub, msgs = list.subscribe("user2@example.org", nil, false, true, key_material) mail = Mail.new mail.to = list.email mail.from = "something@localhost" mail.subject = "Something" mail.body = "Some content" Schleuder::Runner.new().run(mail.to_s, list.email) messages = Mail::TestMailer.deliveries recipients = messages.map { |m| m.to.first }.sort expect(messages.size).to be(3) expect(recipients).to eql(['admin@example.org', 'user1@example.org', 'user2@example.org']) expect(messages[0].reply_to).to eql(mail.from) expect(messages[1].reply_to).to eql(mail.from) expect(messages[2].reply_to).to eql(mail.from) teardown_list_and_mailer(list) end it "prefers reply_to of the sender over from when existing" do list = create(:list, set_reply_to_to_sender: true) key_material = File.read("spec/fixtures/default_list_key.txt") sub, msgs = list.subscribe("admin@example.org", nil, true, true, key_material) sub, msgs = list.subscribe("user1@example.org", nil, false, true, key_material) sub, msgs = list.subscribe("user2@example.org", nil, false, true, key_material) mail = Mail.new mail.to = list.email mail.from = 'something@localhost' mail.subject = 'Something' mail.body = 'Some content' mail.reply_to = 'abc@def.de' Schleuder::Runner.new().run(mail.to_s, list.email) messages = Mail::TestMailer.deliveries recipients = messages.map { |m| m.to.first }.sort expect(messages.size).to be(3) expect(recipients).to eql(['admin@example.org', 'user1@example.org', 'user2@example.org']) expect(messages[0].reply_to).to eql(mail.reply_to) expect(messages[1].reply_to).to eql(mail.reply_to) expect(messages[2].reply_to).to eql(mail.reply_to) teardown_list_and_mailer(list) end end describe "#munge_from" do it "is disabled by default" do list = create(:list) expect(list.munge_from).to be(false) teardown_list_and_mailer(list) end it "does not munge from address when disabled" do list = create(:list, munge_from: false) key_material = File.read("spec/fixtures/default_list_key.txt") sub, msgs = list.subscribe("admin@example.org", nil, true, true, key_material) sub, msgs = list.subscribe("user1@example.org", nil, false, true, key_material) sub, msgs = list.subscribe("user2@example.org", nil, false, true, key_material) mail = Mail.new mail.to = list.email mail.from = 'something@localhost' mail.subject = 'Something' mail.body = "Some content" Schleuder::Runner.new().run(mail.to_s, list.email) messages = Mail::TestMailer.deliveries recipients = messages.map { |m| m.to.first }.sort expect(messages.size).to be(3) expect(recipients).to eql(['admin@example.org', 'user1@example.org', 'user2@example.org']) expect(messages[0].from).to eql([list.email]) expect(messages[1].from).to eql([list.email]) expect(messages[2].from).to eql([list.email]) teardown_list_and_mailer(list) end it "sets from to munged version when enabled" do list = create(:list, munge_from: true) key_material = File.read("spec/fixtures/default_list_key.txt") sub, msgs = list.subscribe("admin@example.org", nil, true, true, key_material) sub, msgs = list.subscribe("user1@example.org", nil, false, true, key_material) sub, msgs = list.subscribe("user2@example.org", nil, false, true, key_material) mail = Mail.new mail.to = list.email mail.from = 'something@localhost' mail.subject = 'Something' mail.body = "Some content" Schleuder::Runner.new().run(mail.to_s, list.email) messages = Mail::TestMailer.deliveries recipients = messages.map { |m| m.to.first }.sort expect(messages.size).to be(3) expect(recipients).to eql(['admin@example.org', 'user1@example.org', 'user2@example.org']) expect(messages[0]['from'].to_s).to eql("\"#{mail.from.first} via #{list.email}\" <#{list.email}>") expect(messages[1]['from'].to_s).to eql("\"#{mail.from.first} via #{list.email}\" <#{list.email}>") expect(messages[2]['from'].to_s).to eql("\"#{mail.from.first} via #{list.email}\" <#{list.email}>") teardown_list_and_mailer(list) end end end schleuder-3.6.0/spec/schleuder/unit/logger_notifications_spec.rb000066400000000000000000000106331401002544500251320ustar00rootroot00000000000000require "spec_helper" describe Schleuder::LoggerNotifications do context 'return path' do it 'sets default superadmin' do list = create(:list, send_encrypted_only: false) list.subscribe("schleuder@example.org", nil, true) list.logger.notify_admin("Something", nil, I18n.t('notice')) message = Mail::TestMailer.deliveries.first expect(message.sender).to eql('root@localhost') expect(message[:Errors_To].to_s).to eql('root@localhost') end it 'sets superadmin' do oldval = Conf.instance.config['superadmin'] Conf.instance.config['superadmin'] = 'schleuder-admin@example.org' list = create(:list, send_encrypted_only: false) list.subscribe("schleuder@example.org", nil, true) list.logger.notify_admin("Something", nil, I18n.t('notice')) message = Mail::TestMailer.deliveries.first expect(message.sender).to eql('schleuder-admin@example.org') expect(message[:Errors_To].to_s).to eql('schleuder-admin@example.org') Conf.instance.config['superadmin'] = oldval end end it "notifies admins of simple text-message" do list = create(:list, send_encrypted_only: false) list.subscribe("schleuder@example.org", nil, true) list.logger.notify_admin("Something", nil, I18n.t('notice')) message = Mail::TestMailer.deliveries.first expect(message.to).to eql(['schleuder@example.org']) expect(message.subject).to eql(I18n.t('notice')) expect(message.first_plaintext_part.body.to_s).to eql("Something") end it "notifies admins of multiple text-messages" do list = create(:list, send_encrypted_only: false) list.subscribe("schleuder@example.org", nil, true) list.logger.notify_admin(["Something", "anotherthing"], nil, I18n.t('notice')) message = Mail::TestMailer.deliveries.first expect(message.to).to eql(['schleuder@example.org']) expect(message.subject).to eql(I18n.t('notice')) expect(message.parts.first.parts.first.body.to_s).to eql("Something") expect(message.parts.first.parts.last.body.to_s).to eql("anotherthing") end it "notifies admins of multiple text-messages and the original message" do list = create(:list, send_encrypted_only: false) list.subscribe("schleuder@example.org", nil, true) mail = Mail.new mail.subject = "A subject" list.logger.notify_admin(["Something", "anotherthing"], mail.to_s, I18n.t('notice')) message = Mail::TestMailer.deliveries.first expect(message.to).to eql(['schleuder@example.org']) expect(message.subject).to eql(I18n.t('notice')) expect(message.parts.first.parts.first.body.to_s).to eql("Something") expect(message.parts.first.parts[1].body.to_s).to eql("anotherthing") expect(message.parts.first.parts[2].body.to_s).to include("Subject: A subject") expect(message.parts.first.parts[2][:content_type].content_type).to eql("message/rfc822") end it "notifies admins encryptedly if their key is usable" do list = create(:list, send_encrypted_only: false) list.subscribe("schleuder@example.org", '59C71FB38AEE22E091C78259D06350440F759BD3', true) mail = Mail.new mail.subject = "A subject" list.logger.notify_admin(["Something", "anotherthing"], mail.to_s, I18n.t('notice')) message = Mail::TestMailer.deliveries.first expect(message.subject).to eql('Notice') expect(message.parts.size).to be(2) expect(message.parts.last.body.to_s).to include('-----BEGIN PGP MESSAGE-----') end it "notifies admins in the clear if their key is unusable" do list = create(:list, send_encrypted_only: false) key_material = File.read("spec/fixtures/partially_expired_key.txt") list.subscribe("schleuder@example.org", nil, true, true, key_material) mail = Mail.new mail.subject = "A subject" list.logger.notify_admin("Something", mail.to_s, I18n.t('notice')) message = Mail::TestMailer.deliveries.first expect(message.subject).to eql('Notice') expect(message.parts.size).to be(2) expect(message.parts.first.parts.first.body.to_s).to eql('Something') end it 'includes a List-Id header in notification mails sent to admins' do list = create(:list, send_encrypted_only: false) list.subscribe("schleuder@example.org", nil, true) mail = Mail.new list.logger.notify_admin("Something", mail.to_s, I18n.t('notice')) message = Mail::TestMailer.deliveries.first expect(message.header['List-Id'].to_s).to eql("<#{list.email.gsub('@', '.')}>") end end schleuder-3.6.0/spec/schleuder/unit/message_spec.rb000066400000000000000000000210771401002544500223520ustar00rootroot00000000000000require "spec_helper" describe Mail::Message do it "doesn't change the order of mime-parts" do text_part = Mail::Part.new text_part.body = "This is text" image_part = Mail::Part.new image_part.content_type = 'image/png' image_part.content_disposition = 'attachment; filename=spec.png' message = Mail.new message.parts << image_part message.parts << text_part # This triggers the sorting. message.to_s expect(message.parts.first.mime_type).to eql('image/png') expect(message.parts.last.mime_type).to eql('text/plain') end # TODO: test message with "null" address ("<>") as Return-Path. I couldn't # bring Mail to generate such a message, yet. it "recognizes a message sent to listname-bounce@hostname as automated message" do list = create(:list) mail = Mail.new # Trigger the setting of mandatory headers. mail.to_s mail = Mail.create_message_to_list(mail.to_s, 'something-bounce@localhost', list).setup expect(mail.automated_message?).to be(true) end it "recognizes bounce message subject using the bounce_email gem" do list = create(:list) mail = Mail.new mail.subject = "Undelivered Mail Returned to Sender" mail = Mail.create_message_to_list(mail.to_s, 'something@localhost', list).setup expect(mail.automated_message?).to be(true) end Dir.glob('spec/fixtures/mails/not_bounces/*') do |filename| it "does not misclassify normal message #{filename} as bounce" do list = create(:list) mail = Mail.new(File.read(filename)) mail = Mail.create_message_to_list(mail.to_s, 'something@localhost', list).setup expect(mail.automated_message?).to be(false) end end Dir.glob('spec/fixtures/mails/bounces/*') do |filename| it "does not misclassify bounce #{filename} as normal message" do list = create(:list) mail = Mail.new(File.read(filename)) mail = Mail.create_message_to_list(mail.to_s, 'something@localhost', list).setup expect(mail.automated_message?).to be(true) end end it "recognizes a cron message with 'Auto-Submitted'-header NOT as automated message" do list = create(:list) mail = Mail.new mail.header['Auto-Submitted'] = 'yes' mail.header['X-Cron-Env'] = '' # Trigger the setting of mandatory headers. mail.to_s mail = Mail.create_message_to_list(mail.to_s, 'something@localhost', list).setup expect(mail.automated_message?).to be(false) end it "recognizes a Jenkins message with 'Auto-Submitted'-header NOT as automated message" do list = create(:list) mail = Mail.new mail.header['Auto-submitted'] = 'auto-generated' mail.header['X-Jenkins-Job'] = 'test_Tails_ISO_stable' # Trigger the setting of mandatory headers. mail.to_s mail = Mail.create_message_to_list(mail.to_s, 'something@localhost', list).setup expect(mail.automated_message?).to be(false) end # https://0xacab.org/schleuder/schleuder/issues/248 it "recognizes a sudo message with 'Auto-Submitted'-header NOT as automated message" do list = create(:list) mail = Mail.new mail.header['Auto-submitted'] = 'auto-generated' mail.subject = '*** SECURITY information for host.example.com ***' # Trigger the setting of mandatory headers. mail.to_s mail = Mail.create_message_to_list(mail.to_s, 'something@localhost', list).setup expect(mail.automated_message?).to be(false) end context '#add_subject_prefix!' do it 'adds a configured subject prefix' do list = create(:list) list.subject_prefix = '[prefix]' list.subscribe('admin@example.org',nil,true) mail = Mail.new mail.from 'someone@example.org' mail.to list.email mail.text_part = 'blabla' mail.subject = 'test' message = Mail.create_message_to_list(mail.to_s, list.email, list).setup message.add_subject_prefix! expect(message.subject).to eql('[prefix] test') end it 'adds a configured subject prefix without subject' do list = create(:list) list.subject_prefix = '[prefix]' list.subscribe('admin@example.org',nil,true) mail = Mail.new mail.from 'someone@example.org' mail.to list.email mail.text_part = 'blabla' message = Mail.create_message_to_list(mail.to_s, list.email, list).setup message.add_subject_prefix! expect(message.subject).to eql('[prefix]') end it 'does not add a subject prefix if already present' do list = create(:list) list.subject_prefix = '[prefix]' list.subscribe('admin@example.org',nil,true) mail = Mail.new mail.from 'someone@example.org' mail.to list.email mail.text_part = 'blabla' mail.subject = 'Re: [prefix] test' message = Mail.create_message_to_list(mail.to_s, list.email, list).setup message.add_subject_prefix! expect(message.subject).to eql('Re: [prefix] test') end end it "adds list#public_footer as last mime-part without changing its value" do footer = "\n\n-- \nblabla\n blabla\n " list = create(:list) list.public_footer = footer mail = Mail.new mail.body = 'blabla' mail.list = list mail.add_public_footer! expect(mail.parts.last.body.to_s).to eql(footer) end it "adds list#internal_footer as last mime-part without changing its value" do footer = "\n\n-- \nblabla\n blabla\n " list = create(:list) list.internal_footer = footer mail = Mail.new mail.body = 'blabla' mail.list = list mail.add_internal_footer! expect(mail.parts.last.body.to_s).to eql(footer) end context "makes a pseudo header" do it "with key / value" do mail = Mail.new ph = mail.make_pseudoheader('notice','some value') expect(ph).to eql('Notice: some value') end it "without value" do mail = Mail.new ph = mail.make_pseudoheader(:key,nil) expect(ph).to eql('Key: ') end it "with empty value" do mail = Mail.new ph = mail.make_pseudoheader(:key,'') expect(ph).to eql('Key: ') end it "that is getting wrapped" do mail = Mail.new ph = mail.make_pseudoheader('notice','adds list#public_footer as last mime-part without changing its value adds list#public_footer as last mime-part without changing its value') expect(ph).to eql("Notice: adds list#public_footer as last mime-part without changing its value\n adds list#public_footer as last mime-part without changing its value") expect(ph.split("\n")).to all( satisfy{|l| l.length <= 78 }) end it "that multiline are getting wrapped" do mail = Mail.new ph = mail.make_pseudoheader('notice',"adds list#public_footer as last mime-part\nwithout changing its value adds list#public_footer as last mime-part without changing its value") expect(ph).to eql("Notice: adds list#public_footer as last mime-part\n without changing its value adds list#public_footer as last mime-part without\n changing its value") expect(ph.split("\n")).to all( satisfy{|l| l.length <= 78 }) end it "that single multiline are getting indented" do mail = Mail.new ph = mail.make_pseudoheader('notice',"on line 1\non line 2 but indented") expect(ph).to eql("Notice: on line 1\n on line 2 but indented") expect(ph.split("\n")).to all( satisfy{|l| l.length <= 78 }) end it "that a line with less than 76 gets wrapped" do mail = Mail.new ph = mail.make_pseudoheader('keylongerthan8', 'afafa afafaf' * 6) # message is 72 long expect(ph).to eql("Keylongerthan8: afafa afafafafafa afafafafafa afafafafafa afafafafafa\n afafafafafa afafaf") expect(ph.split("\n")).to all( satisfy{|l| l.length <= 78 }) end it "that a multiline with less than 76 get wrapped correctly on the first line" do mail = Mail.new ph = mail.make_pseudoheader('keylongerthan8', ('afafa afafaf' * 6)+"\nbla bla newline") expect(ph).to eql("Keylongerthan8: afafa afafafafafa afafafafafa afafafafafa afafafafafa\n afafafafafa afafaf\n bla bla newline") expect(ph.split("\n")).to all( satisfy{|l| l.length <= 78 }) end it "that a multiline with less than 76 get wrapped correctly on the first line and the following lines" do mail = Mail.new ph = mail.make_pseudoheader('keylongerthan8', ('afafa afafaf' * 6)+"\nbla bla newline"+('afafa afafaf' * 6)) expect(ph).to eql("Keylongerthan8: afafa afafafafafa afafafafafa afafafafafa afafafafafa\n afafafafafa afafaf\n bla bla newlineafafa afafafafafa afafafafafa afafafafafa afafafafafa\n afafafafafa afafaf") expect(ph.split("\n")).to all( satisfy{|l| l.length <= 78 }) end end end schleuder-3.6.0/spec/schleuder/unit/subscription_spec.rb000066400000000000000000000110071401002544500234420ustar00rootroot00000000000000require "spec_helper" describe Schleuder::Subscription do BOOLEAN_SUBSCRIPTION_ATTRIBUTES = [ :delivery_enabled, :admin ].freeze it "has a valid factory" do subscription = create(:subscription) expect(subscription).to be_valid end it { is_expected.to respond_to :list_id } it { is_expected.to respond_to :email } it { is_expected.to respond_to :fingerprint } it { is_expected.to respond_to :admin } it { is_expected.to respond_to :delivery_enabled } it "is invalid when list_id is blank" do subscription = build(:subscription, list_id: "") expect(subscription).not_to be_valid expect(subscription.errors.messages[:list_id]).to be_present end it "is invalid when email is nil" do list = create(:list) subscription = build(:subscription, list_id: list.id, email: nil) expect(subscription).not_to be_valid expect(subscription.errors.messages[:email]).to include("can't be blank") end it "is invalid when email is blank" do list = create(:list) subscription = build(:subscription, list_id: list.id, email: "") expect(subscription).not_to be_valid expect(subscription.errors.messages[:email]).to include("can't be blank") end it "is invalid when email does not contain an @" do list = create(:list) subscription = build(:subscription, list_id: list.id, email: "fooatbar.org") expect(subscription).not_to be_valid expect(subscription.errors.messages[:email]).to include("is not a valid email address") end it "formats email address when email begins with a space" do list = create(:list) subscription = build(:subscription, list_id: list.id, email: " foo@bar.org") expect(subscription).to be_valid expect(subscription.email).to be_eql('foo@bar.org') expect(subscription.errors.messages[:email]).to be_blank end it "is valid when fingerprint is empty" do list = create(:list) subscription = build(:subscription, list_id: list.id, fingerprint: "") expect(subscription).to be_valid expect(subscription.errors.messages[:fingerprint]).to be_blank end it "is valid when fingerprint is nil" do list = create(:list) subscription = build(:subscription, list_id: list.id, fingerprint: nil) expect(subscription).to be_valid expect(subscription.errors.messages[:fingerprint]).to be_blank end it "is invalid when fingerprint contains invalid characters" do list = create(:list) subscription = build(:subscription, list_id: list.id, fingerprint: "&$$$$123AAA") expect(subscription).not_to be_valid expect(subscription.errors.messages[:fingerprint]).to include("is not a valid OpenPGP-fingerprint") end BOOLEAN_SUBSCRIPTION_ATTRIBUTES.each do |subscription_attribute| it "is invalid if #{subscription_attribute} is nil" do list = create(:list) subscription = build(:subscription, list_id: list.id) subscription[subscription_attribute] = nil expect(subscription).not_to be_valid expect(subscription.errors.messages[subscription_attribute]).to include("must be true or false") end it "is invalid if #{subscription_attribute} is blank" do list = create(:list) subscription = build(:subscription, list_id: list.id) subscription[subscription_attribute] = "" expect(subscription).not_to be_valid expect(subscription.errors.messages[subscription_attribute]).to include("must be true or false") end end it "is invalid if the given email is already subscribed for the list" do list1 = create(:list) list2 = create(:list) subscription1 = create(:subscription, list_id: list1.id) subscription2 = create(:subscription, list_id: list2.id, email: subscription1.email) subscription3 = build(:subscription, email: subscription1.email, list_id: subscription1.list_id) expect(subscription1).to be_valid expect(subscription2).to be_valid expect(subscription3).not_to be_valid expect(subscription3.errors[:email]).to eql(["is already subscribed"]) end describe "#fingerprint" do it "transforms the fingerprint to upper case" do subscription = Schleuder::Subscription.new(email: "example@example.org", fingerprint: "c4d60f8833789c7caa44496fd3ffa6613ab10ece") expect(subscription.fingerprint).to eq("C4D60F8833789C7CAA44496FD3FFA6613AB10ECE") end end it "removes whitespaces and 0x from the fingerprint" do fingerprint = "0x 99 991 1000 10" subscription = build(:subscription, fingerprint: fingerprint) expect(subscription.fingerprint).to eq "99991100010" end end schleuder-3.6.0/spec/sks-mock.rb000077500000000000000000000016321401002544500165040ustar00rootroot00000000000000#!/usr/bin/env ruby require 'sinatra/base' class SksMock < Sinatra::Base set :environment, :production set :port, 9999 set :bind, 'localhost' get '/status' do 'ok' end get '/keys/example.asc' do File.read('spec/fixtures/expired_key_extended.txt') end get '/pks/lookup' do case params['search'] when '0x98769E8A1091F36BD88403ECF71A3F8412D83889', 'admin@example.org' File.read('spec/fixtures/expired_key_extended.txt') when '0x6EE51D78FD0B33DE65CCF69D2104E20E20889F66', 'old@example.org' File.read('spec/fixtures/olduid_key_with_newuid.txt') when '0x59C71FB38AEE22E091C78259D06350440F759BD3' File.read('spec/fixtures/default_list_key.txt') when '0x87E65ED2081AE3D16BE4F0A5EBDBE899251F2412' File.read('spec/fixtures/openpgp-keys/public-key-with-third-party-signature.txt') else 404 end end # Run this class as application run! end schleuder-3.6.0/spec/smtp-daemon.rb000077500000000000000000000032311401002544500171760ustar00rootroot00000000000000#!/usr/bin/env ruby # # This script is a very simple SMTP-daemon, that dumps every incoming email # into the given directory. It's meant to capture messages from schleuder-lists # during test-runs. require 'socket' require 'open3' trap ("INT") { exit 0 } def usage puts "Usage: #{File.basename(__FILE__)} portnum output-directory" exit 1 end # get args if ARGV.first.to_s.match('(-h|--help|help)') || ARGV.empty? usage end port = ARGV.first.to_i if port == 0 usage end outputdir = ARGV[1].to_s if outputdir.empty? usage elsif ! File.directory?(outputdir) puts "Not a directory: #{outputdir}" exit 1 end begin # run the server server = TCPServer.new("localhost", port) # receive input while (connection = server.accept) input = '' recipient = '' connection.puts "220 localhost SMTP" begin while line = connection.gets line.chomp! case line[0..3].downcase when 'ehlo', 'helo' connection.puts "250 localhost" when 'mail', 'rset' connection.puts "250 ok" when 'rcpt' recipient = line.split(':').last.gsub(/[<>\s]*/, '') connection.puts "250 ok" when 'data' connection.puts "354 go ahead" when 'quit' connection.puts "221 localhost" when '.' filename = File.join(outputdir, "mail-#{Time.now.to_f}") # puts "New message to #{recipient} written to #{filename}" IO.write(filename, input) connection.puts "250 ok" else input << line + "\n" end end rescue IOError end connection.close end rescue => exc $stderr.puts exc exit 1 end schleuder-3.6.0/spec/spec_helper.rb000066400000000000000000000121141401002544500172400ustar00rootroot00000000000000ENV['SCHLEUDER_ENV'] ||= 'test' ENV['SCHLEUDER_CONFIG'] = 'spec/schleuder.yml' ENV["SCHLEUDER_LIST_DEFAULTS"] = "etc/list-defaults.yml" if ENV['USE_BUNDLER'] != 'false' require 'bundler/setup' Bundler.setup end # We need to do this before requiring any other code # Check env if we want to run code coverage analysis if ENV['CHECK_CODE_COVERAGE'] == 'true' require 'simplecov' require 'simplecov-console' SimpleCov::Formatter::Console.table_options = {max_width: 400} SimpleCov.formatter = SimpleCov::Formatter::Console SimpleCov.start do add_filter %r{^/vendor/} add_filter %r{^/spec/} end end require 'schleuder' require 'schleuder/cli' require 'database_cleaner' require 'factory_bot' require 'net/http' require 'fileutils' require 'socket' RSpec.configure do |config| config.expect_with :rspec do |expectations| expectations.include_chain_clauses_in_custom_matcher_descriptions = true end config.order = :random config.include FactoryBot::Syntax::Methods config.before(:suite) do FactoryBot.find_definitions end config.before(:suite) do DatabaseCleaner.strategy = :deletion DatabaseCleaner.clean_with(:truncation) end config.around(:each) do |example| Mail::TestMailer.deliveries.clear DatabaseCleaner.cleaning do example.run end end config.after(:each) do |example| FileUtils.rm_rf(Dir["spec/gnupg/pubring.gpg~"]) # gpgconf --kill might hang indefinitely in IPv6-only environments. `pkill -f "#{Conf.lists_dir}" || true` end config.after(:suite) do cleanup_gnupg_home stop_smtp_daemon end # rspec-mocks config goes here. You can use an alternate test double # library (such as bogus or mocha) by changing the `mock_with` option here. config.mock_with :rspec do |mocks| mocks.verify_partial_doubles = true end Mail.defaults do delivery_method :test end def cleanup_gnupg_home ENV["GNUPGHOME"] = nil FileUtils.rm_rf Schleuder::Conf.lists_dir end def smtp_daemon_outputdir File.join(Conf.lists_dir, 'smtp-daemon-output') end def with_sks_mock(listdir) # Do we deal with an IPv6-only environment? # If so, handle dirmngr specifically so it's able to cope with it. # No idea what's the relation in regards to 'no-use-tor', but it helps. if ! Socket.ip_address_list.find { |ai| ai.ipv4? && ai.ipv4_loopback? } `printf "disable-ipv4\nno-use-tor" > "#{listdir}/dirmngr.conf"` end pid = Process.spawn('spec/sks-mock.rb', [:out, :err] => ["/tmp/sks-mock.log", 'w']) uri = URI.parse("http://localhost:9999/status") attempts = 25 # Use the following env var to increase the time to sleep between # each attempt, for example if building the Debian package ENV['SKS_MOCK_SLEEP'] ||= '1' begin sleep ENV['SKS_MOCK_SLEEP'].to_i Net::HTTP.get(uri) rescue Errno::ECONNREFUSED => exc attempts -= 1 if attempts > 0 retry else raise "sks-mock.rb failed to start, cannot continue: #{exc}" end end yield Process.kill 'TERM', pid Process.wait pid end def start_smtp_daemon if File.directory?(smtp_daemon_outputdir) # Try to kill it, in case it's still around (this occurred on some # systems). stop_smtp_daemon end if ! File.directory?(smtp_daemon_outputdir) FileUtils.mkdir_p(smtp_daemon_outputdir) end daemon = File.join('spec', 'smtp-daemon.rb') pid = Process.spawn(daemon, '2523', smtp_daemon_outputdir) pidfile = File.join(smtp_daemon_outputdir, 'pid') IO.write(pidfile, pid) end def stop_smtp_daemon pidfile = File.join(smtp_daemon_outputdir, 'pid') if File.exist?(pidfile) pid = File.read(pidfile).to_i Process.kill(15, pid) FileUtils.rm_rf smtp_daemon_outputdir end end def run_schleuder(command, email, message_path) `SCHLEUDER_ENV=test SCHLEUDER_CONFIG=spec/schleuder.yml bin/schleuder #{command} #{email} < #{message_path} 2>&1` end def run_cli(command) `SCHLEUDER_ENV=test SCHLEUDER_CONFIG=spec/schleuder.yml bin/schleuder #{command} 2>&1` end def with_env(env) backup = ENV.to_hash ENV.replace(env) yield ensure ENV.replace(backup) end def process_mail(msg, recipient) output = nil begin output = Schleuder::Runner.new.run(msg, recipient) rescue SystemExit end output end def teardown_list_and_mailer(list) FileUtils.rm_rf(list.listdir) Mail::TestMailer.deliveries.clear end def encrypt_string(list, str) _, ciphertext, _ = list.gpg.class.gpgcli("--recipient #{list.fingerprint} --encrypt") do |stdin, stdout, stderr| stdin.puts str # Apparently it differs between ruby-version if we have to close the stream manually. stdin.close if ! stdin.closed? stdout.readlines end ciphertext.reject { |line| line.match(/^\[GNUPG:\]/) }.join end def with_tmpfile(content,&blk) file = Tempfile.new('temporary-file',Conf.lists_dir) begin file.write(content) file.close yield file.path ensure file.unlink end end def t(*args) I18n.t(*args) end end