{"id":43550857,"url":"https://github.com/dullgiulio/perso","last_synced_at":"2026-02-03T19:30:43.239Z","repository":{"id":29663041,"uuid":"33205121","full_name":"dullgiulio/perso","owner":"dullgiulio","description":"Personal Maildir-to-REST server ","archived":false,"fork":false,"pushed_at":"2017-02-06T13:39:27.000Z","size":528,"stargazers_count":112,"open_issues_count":1,"forks_count":3,"subscribers_count":7,"default_branch":"master","last_synced_at":"2024-06-20T12:49:46.448Z","etag":null,"topics":["go","maildir","rest"],"latest_commit_sha":null,"homepage":null,"language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dullgiulio.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2015-03-31T19:25:21.000Z","updated_at":"2024-06-20T12:49:46.450Z","dependencies_parsed_at":"2022-09-03T16:50:38.604Z","dependency_job_id":null,"html_url":"https://github.com/dullgiulio/perso","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/dullgiulio/perso","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dullgiulio%2Fperso","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dullgiulio%2Fperso/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dullgiulio%2Fperso/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dullgiulio%2Fperso/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dullgiulio","download_url":"https://codeload.github.com/dullgiulio/perso/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dullgiulio%2Fperso/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29054651,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-03T15:43:47.601Z","status":"ssl_error","status_checked_at":"2026-02-03T15:43:46.709Z","response_time":96,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["go","maildir","rest"],"created_at":"2026-02-03T19:30:42.440Z","updated_at":"2026-02-03T19:30:43.232Z","avatar_url":"https://github.com/dullgiulio.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# perso - Maildir to REST\n\n## About\n\nPerso is a small, self-contained REST server for a Maildir mailbox.\n\nIt includes configurable header indexing and crawling.\n\nPerso is useful when used on testing or staging sites to have a quick\nmeans to access a mailbox remotely, for example by a integration testing\nframework.\n\nPerso can make you forget about POP/IMAP servers for simple use cases.\n\n## Getting Started\n\nDownload the binary (see downloads below) or build it with Go:\n\n```sh\n$ go get -u github.com/dullgiulio/perso\n$ cd $GOPATH/src/github.com/dullgiulio/perso\n$ go install\n```\n\nAfter that, cd to a directory containing e-mail messages (a Maildir,\nusually containing subdirectories 'cur', 'new' and 'tmp'). And, presto, you\ncan run \"perso\".\n\n```sh\n$ cd ~/Mail/ # For example\n$ $GOPATH/bin/perso\n\n```\n\nNow perso is listening on port 8888. Just point your browser to\nhttp://localhost:8888/ to proceed. You should be able to see your latest\nemail message.\n\nA short help is also available: http://localhost:8888/help\n\nGood, that was it. Read on if you want to know what you just did!\n\n## How does it work?\n\nPerso works in a very simple way: first it reads all email messages it finds,\nthen makes an index for each indexed header. By default, it indices 'To' and\n'From'.\n\nFor each indexed header, you can go through the matching messages in\nchronological order.\n\n```\n/from/hello@mysite.com/latest/0\n```\n\nThe first part is the header we want to use to select (in lowercase, so that\n'X-Mailer' becomes just 'x-mailer'). The second part is the value we want the\nheader to have (or contain, see below).\n\nFinally, '/latest/N' will give the Nth message from the newest, while\n'/older/N' will grab starting from the oldest you have.\n\nYou can specify your own headers to index when you start \"presto\", see the\ninvocation section below.\n\nInstead of just a number, the last part of the URL can be a range (N-M) or\nN,M meaning: from mail N, M messages. Ranges are inclusive (Mth mail is shown.)\n\nThe messages will be shown in 'mbox' format. In other words, full RFC 2822,\nwith a \"From MAILER-DAEMON-PERSO...\" line between each message. The content of the 'Form'\nseparator is configurable for easy splitting (mbox format sucks, sorry).\n\n## Invocation\n\n```sh\n$ perso -help\nUsage of perso:\n  -A Header containing addresses (defaults to 'From' and 'To')\n  -H Header to index as-is\n  -P Header that can be matched by a substring\n  -a What to write after 'From ' in mbox format\n  -i Interval between runs of the crawler\n  -s Where to listen from (default: 0.0.0.0:8888)\n```\n\nAfter all options, you can specify the directory containing your messages. If none is\nspecified, perso will index the current directory.\n\nYou can specify multiple headers to index (in addition to 'From' and 'To': they are\nalways indexed). For example, you want to make a 'permalink' to your messages:\n\n```sh\n$ perso -A Message-ID mail-directory/\n```\n\nIf a header contains addresses, use '-A' instead of '-H'.\n\nFinally, use '-F' if you want to be able to match the contents of a header with\n\"fuzzy search\" (case-insensitive submatches).\n\n```sh\n$ perso -P User-Agent mail-directory/\n```\n\nThe '-a' flag can be used to modify the 'mbox' separator line (see above).\n\nTo modify how often to check for changes inside the mail directory, use '-i':\n\n```sh\n$ perso -i 2m\n```\n\nHere for example we index the current directory and check for changes every two\nminutes.\n\n## Example setup with Postfix\n\nIn this example, we setup Postfix to always send a copy of each outgoing email to\na local mailbox. Keep in mind that this is a privacy violation (also, illegal in\nmany Countries) and should only be done on test machines.\n\nTo send everything to a local mailbox, add this to /etc/postfix/main.cf:\n\n```\nalways_bcc = my-mailbox@localhost\n```\n\nYou probably also want to catch everything and send it to some test account on\nanother server (main corporate mail server, for example):\n\nAdd this to main.cf:\n\n```\nrecipient_canonical_maps = regexp:/etc/postfix/recipient_map.regexp\nsender_canonical_maps = regexp:/etc/postfix/sender_map.regexp\nlocal_header_rewrite_clients = static:all\n\nvirtual_mailbox_domains = test.mailbox\nvirtual_mailbox_base = /var/mail\nvirtual_mailbox_maps = regexp:/etc/postfix/maildir_map.regexp\nvirtual_uid_maps = static:111\nvirtual_gid_maps = static:222\n```\n\nSubstitute 111 with the UID of the user you want to own the mail. Same goes for\nthe 222 as GID.\n\nThis will create a mailbox called \"test.mailbox\" inside /var/mail.\n\nLet's see the contents of the mapping files:\n\n```sh\n$ cat /etc/postfix/maildir_map.regexp\n/.*/    test.mailbox/\n$ cat /etc/postfix/recipient_map.regexp\n/(.*)@localhost/ ${1}@localhost\n/^([^@]*)@(.*)$/!^(my\\-name).*^ my-name@mail-server.com\n$ cat /etc/postfix/sender_map.regexp\n/^([^@]*)@(.*)$/!^(my\\-name).*^ my-name@mail-server.com\n```\n\nAfter any changes, remember to restart postfix:\n\n```sh\n# service reload postfix\n```\n\nThen start perso (under a screen/tmux session is best):\n\n```sh\n$ perso -A Message-Id -i 1s /var/mail/test.mailbox/\n```\n\nAnd voila, it's running. New messages are detected every second.\n\n## Example setup with Exim\n\nPull request welcome!\n\n## Downloads\n\nAvailable as Github releases: https://github.com/dullgiulio/perso/releases\n\n## Bugs\n\nPlease report bugs or suggestions: https://github.com/dullgiulio/perso/issues\n\n## References\n\n1. Maildir: http://cr.yp.to/proto/maildir.html\n2. mbox format: https://en.wikipedia.org/wiki/Mbox\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdullgiulio%2Fperso","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdullgiulio%2Fperso","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdullgiulio%2Fperso/lists"}