SMTP (email) server with a focus on simplicity, security, and ease of operation [mirror]

chasquid

chasquid is an SMTP (email) server with a focus on simplicity, security, and ease of operation.

It is designed mainly for individuals and small groups.

It's written in Go, and distributed under the Apache license 2.0.

Gitlab CI status Cirrus-CI Status Go Report Card Coverage
Docs OFTC IRC

Features

  • Easy
    • Easy to configure.
    • Hard to mis-configure in ways that are harmful or insecure (e.g. no open relay, or clear-text authentication).
    • Monitoring HTTP server, with exported variables and tracing to help debugging.
    • Integrated with Debian, Ubuntu, and Arch.
    • Supports using Dovecot for authentication.
  • Useful
    • Multiple/virtual domains, with per-domain users and aliases.
    • Suffix dropping (user+something@domainuser@domain).
    • Hooks for integration with greylisting, anti-virus, anti-spam, and DKIM/DMARC.
    • International usernames (SMTPUTF8) and domain names (IDNA).
  • Secure
    • Tracking of per-domain TLS support, prevents connection downgrading.
    • Multiple TLS certificates.
    • Easy integration with Let's Encrypt.
    • SPF and MTA-STS checking.

Documentation

The how-to guide and the installation guide are the best starting points on how to install, configure and run chasquid.

You will find all documentation here.

Contact

If you have any questions, comments or patches, please send them to the mailing list, [email protected].
To subscribe, send an email to [email protected].

Security issues can be reported privately to [email protected].

Bug reports and pull requests on GitHub are also welcome.

You can also reach out via IRC, #chasquid on OFTC.

Comments
  • Error while installing chasquid-1.6-1 on Arch Linux

    Error while installing chasquid-1.6-1 on Arch Linux

    I'm trying to install chasquid-1.6-1 on Arch Linux and i'm getting following error:

    ==> Starting check()...
    ?   	blitiri.com.ar/go/chasquid	[no test files]
    ?   	blitiri.com.ar/go/chasquid/cmd/chasquid-util	[no test files]
    ?   	blitiri.com.ar/go/chasquid/cmd/dovecot-auth-cli	[no test files]
    ?   	blitiri.com.ar/go/chasquid/cmd/mda-lmtp	[no test files]
    ?   	blitiri.com.ar/go/chasquid/cmd/smtp-check	[no test files]
    ?   	blitiri.com.ar/go/chasquid/cmd/spf-check	[no test files]
    ok  	blitiri.com.ar/go/chasquid/internal/aliases	(cached)
    ok  	blitiri.com.ar/go/chasquid/internal/auth	(cached)
    ok  	blitiri.com.ar/go/chasquid/internal/config	(cached)
    ok  	blitiri.com.ar/go/chasquid/internal/courier	(cached)
    ok  	blitiri.com.ar/go/chasquid/internal/domaininfo	(cached)
    ok  	blitiri.com.ar/go/chasquid/internal/dovecot	(cached)
    ok  	blitiri.com.ar/go/chasquid/internal/envelope	(cached)
    ok  	blitiri.com.ar/go/chasquid/internal/expvarom	(cached)
    ok  	blitiri.com.ar/go/chasquid/internal/haproxy	(cached)
    ok  	blitiri.com.ar/go/chasquid/internal/maillog	(cached)
    ok  	blitiri.com.ar/go/chasquid/internal/normalize	(cached)
    ok  	blitiri.com.ar/go/chasquid/internal/protoio	(cached)
    ?   	blitiri.com.ar/go/chasquid/internal/protoio/testpb	[no test files]
    ok  	blitiri.com.ar/go/chasquid/internal/queue	(cached)
    ok  	blitiri.com.ar/go/chasquid/internal/safeio	(cached)
    ok  	blitiri.com.ar/go/chasquid/internal/set	(cached)
    ok  	blitiri.com.ar/go/chasquid/internal/smtp	(cached)
    ok  	blitiri.com.ar/go/chasquid/internal/smtpsrv	(cached)
    ok  	blitiri.com.ar/go/chasquid/internal/sts	(cached)
    ok  	blitiri.com.ar/go/chasquid/internal/testlib	(cached)
    ok  	blitiri.com.ar/go/chasquid/internal/tlsconst	(cached)
    ?   	blitiri.com.ar/go/chasquid/internal/trace	[no test files]
    ok  	blitiri.com.ar/go/chasquid/internal/userdb	(cached)
    ?   	blitiri.com.ar/go/chasquid/test/util	[no test files]
    t-01-simple_local ...
    .msmtp-bin: cannot locate host testserver: Name or service not known
    .msmtp-bin: could not send mail (account default from msmtprc)
    ==> ERROR: A failure occurred in check().
        Aborting...
    

    So it looks to me like some test is not passing while installation and therefore whole procedure fails.

  • introduce catch-all alias resolution

    introduce catch-all alias resolution

    A "catch-all" alias is an optional, special form of an alias that applies in a very last step of resolution (i.e. after running aliases hooks), if no aliases could be found for the user name so far.

    Addresses GitHub issue #23.

  • feat(smtpserv): add support for HAProxy Proxy protocol

    feat(smtpserv): add support for HAProxy Proxy protocol

    Add support for HAProxy's Proxy Protocol (opt-in).

    By default Chasquid gets the remote IP address from the TCP connection to perform the SPF detection. Unfortunately when the SMTP server is behind a load balancer (e.g: Kubernetes' Load Balancer or a simple HA Proxy LB), the SPF check will fail because the Load Balancer IP address (e.g: 10.42.0.1 for Kubernetes kube-proxy) doesn't match the one specified in the SPF domain record.

    For this reason with this PR HAProxy's Proxy Protocol support can be enabled using the proxy_protocol config element.

    This will therefore start to read on every new connection the PROXY line:

    PROXY TCP4 193.169.253.128 178.63.0.254 53572 25
    

    and will then replace the sourceIp with the one provided by HAProxy, so that the SPF check can succeed (if the remote IP address matches the SPF record).

  • Question about catch-all aliases

    Question about catch-all aliases

    Hi,

    i have a question about configuration.

    For instance, i've already got "foo@mydomain" and "bar@mydomain" addresses defined in my configuration for some specific users, but i want to have a "catch all" rule, which catches mails sent to unresolvable user (e.g. "unknown@mydomain") and delivers them to some configured user (like, mine)?

    Is that possible to configure such kind of "catch all" rule for aliases?

  • Hooks seem to be ignored

    Hooks seem to be ignored

    Thanks for this cool piece of software!

    I was trying to get the hooks working, but they seem to be ignored. My /etc/chasquid/hooks folder looks like this:

    -rwxr-xr-x+ 1 chasquid chasquid  116 Feb  5 13:23 alias-exists*
    -rwxr-xr-x+ 1 chasquid chasquid   92 Feb  5 13:12 alias-resolve*
    -rwxr-xr-x+ 1 chasquid chasquid 2.2K Jan 19  2019 post-data*
    

    alias-exists:

    #!/bin/bash
    set -e
    
    logger "Called alias-exists"
    
    exit 1
    

    alias-resolve:

    #!/bin/bash
    set -e
    
    logger "Called alias-resolve"
    

    When I run chasquid-util aliases-resolve "[email protected]" I expect the syslog to show my two log strings, but it doesn't. When I try to send an email to the server, nothing happens either. What am I missing here?

  • Add -hostname CLI flag

    Add -hostname CLI flag

    Allows overriding the configured hostname.

    I'm using this in a docker container to have -hostname $HOSTNAME in the startup script, to be able to configure the hostname at runtime. This can also help to use the output of hostname --fqdn as the hostname as requested here.

    PS: Once my container is all done, I'll send a message on the mailing list with a link and explanation for how it differs from the one in the repo :)

  • SpamAssassin integration in Ubuntu 16.04 needs adjustment

    SpamAssassin integration in Ubuntu 16.04 needs adjustment

    This is not necessarily an issue (but could be) but more of a hint for anyone who struggles with spamc not being able to connect to spamd.

    At least on Ubuntu SpamAssassin comes (at least on 16.04, don't know how it is with newer versions) per default set up to use a socket. But that's something chasquid seems not to expect and therefor spamc will fail. The call of spamc in the post-data hook (in the chasquid configs) needs to be adjusted accordingly --socket /YourSocketPath).

    As I said, this was meant primarily for anyone who runs into the same problem, so they don't have to figure it all out themselves.

    BUT maybe just as an idea: since chasquid anyways checks whether spamc exists - maybe check whether spamd is running and if so on which port/socket and adjust the call automatically. I don't know how easy this can be done to work on all of the supported platforms (does netstat look everywhere the same? does spamc even call necessarily spamd or could it also call other daemons, or is spamd even called on every system spamd?)

  • Question about symlinking the certbot pem files...

    Question about symlinking the certbot pem files...

    In the README which was generated inside /etc/chasquid/certs, it is recommended using a symlink to point to /etc/letsencrypt/live/rapidev.org/{privkey,fullchain}.pem

    Note the directory structure matches certbot's structure, so if you use it you can just create symlinks to /etc/letsencrypt/live/.

    This is a great idea! Especially since my certs need regen every 90 days. I have a lot of subdomains, which equates to an entire day of headache every few months. Each cuttable corner is a blessing!

    The issue is that the very next line in the README states:

    Note also that the certificates and private keys must be readable by the chasquid user.

    I don't see how these (symlinking and readability) can coexist when we arent allowed to change the modes of the files in /etc/letsencrypt/live. Ive already created softlinks with ln -s, but soft links look at the original for permissions.

    For example, the filemode for my linked files are now 777 ( rwxrwxrwx ), yet cat fullchain.pem still outputs "permission denied."

    The only workaround I can think of is to remove the -s flag from the ln command, but this is pointless because then the certs will not auto-update when I update the originals, and that is the only reason for linking in the first place. Is their a way around this?

    Thanks in advance for your help! And for the MTA!

  • Use dkimpy for generating DKIM signatures

    Use dkimpy for generating DKIM signatures

    Compared to driusan/dkim, dkimpy is actively maintained and available on many distros (Ubuntu, Fedora, Debian, etc).

    This PR would make enabling DKIM an easier procedure, without cloning driusan/dkim or compile & install.

  • docker container won't restart due to dublicate hostname option in chasquid.conf

    docker container won't restart due to dublicate hostname option in chasquid.conf

    When the chasquid docker container is restarted, either manually or by docker, the entrypoint.sh echos the configuration option "hostname: < actual hostname >" into the chasquid.conf again resulting in:

    Recreating chasquid ... done
    Attaching to chasquid
    chasquid      | _ chasquid.go:70     chasquid starting (version undefined)
    chasquid      | ☠ chasquid.go:77     Error loading config: parsing config: proto: (line 28:1): non-repeated field "hostname" is repeated
    

    this is simply due to this line in entrypoint.sh:

    # Pick the default domain as default hostname for chasquid. This is only used
    # in plain text sessions and on very rare cases, and it's mostly for aesthetic
    # purposes.
    echo "hostname: '$ONE_DOMAIN'" >> /etc/chasquid/chasquid.conf
    
  • TLS Certificate reloading

    TLS Certificate reloading

    Hello, I hope 2020 hasn't treated you too horribly.

    I've been using chasquid for a while with a custom docker setup, and my only nit left is when my certificate expires, chasquid doesn't reload it on its own. The solution recommended in the how-to is to use a certbot hook. Unfortunately I can't use that as is because certbot and chasquid run in different containers and only "communicate" via the shared certs directory.

    I think adding a FS watcher is overkill (and I'm not even sure it would work across overlayfs/docker volumes), but maybe an HTTP endpoint would be fine. Because of my setup, the HTTP endpoint wouldn't need to be authenticated as I can not expose it to the internet, just to the docker network. So adding an insecure /api endpoint disabled by default could be a simple solution.

    Would you be willing to merge something like that? Or have a better idea?

  • docker: setfacl step fails when using user-provided certificates

    docker: setfacl step fails when using user-provided certificates

    I want to use chasquid in my cloud environment (k8s) and had a look at the bundled Dockerfile, however, there is an issue: in entrypoint.sh there is an assumption, that certificates are located inside the Docker container, or created on its filesystem.

    However, it's not applicable in my use case: i want the certificates to be managed/renewed by cert-manager and i want just mount them into chasquid's container, but in this case the setfacl logic is not working.

    @albertito Can you suggest here something? Should i use my own version of Dockerfile / entrypoint.sh?

  • Add support for specifying outbound source IP address (i.e. for multi-homed servers)

    Add support for specifying outbound source IP address (i.e. for multi-homed servers)

    In case of multi-homed servers (having multiple public interfaces, with multiple default routes but using routing policies) it would be useful to have an option to specify the local IP address that should be used to connect from (i.e. bind(local_address) then connect(remote_address)).

    This should be configurable through the configuration file, for example: smtp_local_address = "9.9.9.9".

    In fact, by default this IP address should be initialized with the IP from smtp_address, as most likely the IP used to accept inbound SMTP connections should also be used for outbound SMTP connections. (And in case that is missing, just use 0.0.0.0 as it currently is.)


    Looking at the source code, I assume that one could just change: https://github.com/albertito/chasquid/blob/master/internal/courier/smtp.go#L128

    	conn, err := net.DialTimeout("tcp", mx+":"+*smtpPort, smtpDialTimeout)
    

    with

            localAddress = ...
            remoteAddress, err := net.ResolveTCPAddr("tcp", mx+":"+*smtpPort)
            ...
    	conn, err := net.DialTcp("tcp", localAddress, remoteAddress)
            ...
    

    However that loses the smtpDialTimeout functionality.

    Or perhaps using the net.Dialer type, although that might be somewhat more complex.

  • `chasquid-util aliases-resolve` does not take hooks into account

    `chasquid-util aliases-resolve` does not take hooks into account

    This is forked from issue #17, where @DiederikvandenB reported that chasquid-util aliases-resolve does not take hooks into account, and that is confusing and misleading.

    At minimum, the documentation should mention this fact, and possibly a warning should be emitted if the hooks are present.

    There is no way to manually do an alias resolution with hooks for troubleshooting (other than sending an email, of course), which should also be fixed.

:incoming_envelope: Simple email interface across multiple service providers (ses, postmark, mandrill, smtp)
:incoming_envelope: Simple email interface across multiple service providers (ses, postmark, mandrill, smtp)

go-mail Lightweight email package with multi-provider support (ses, mandrill, postmark) Table of Contents Installation Documentation Examples & Tests

Dec 10, 2022
envio de email via SMTP com anexo usando Go

gosendmail - SMTP This repo is a simple net/smtp abstraction for sending emails using SMTP. With it we can send emails With copy, with blind copy and

Aug 18, 2022
Pretty wrapper for sending email using go net/smtp

Emailer A pretty wrapper around go net/smtp send multiple email using single client func main() { var client *emailer.Client var clientX sync.Mute

Mar 23, 2022
Email-searcher - Given a domain name and real name, attempt to find an existing email for that user.

email-searcher Given a domain name and real name, attempt to find an existing email for that user. Using Run it with both the domain and name flags, l

Jan 2, 2022
VMail - check the markup (HTML, CSS) of HTML email template compatibility with email clients
VMail - check the markup (HTML, CSS) of HTML email template compatibility with email clients

VMail - check the markup (HTML, CSS) of HTML email template compatibility with email clients Email clients use different rendering standards. This is

Dec 17, 2022
Disposable webmail server (similar to Mailinator) with built in SMTP, POP3, RESTful servers; no DB required.
Disposable webmail server (similar to Mailinator) with built in SMTP, POP3, RESTful servers; no DB required.

Disposable webmail server (similar to Mailinator) with built in SMTP, POP3, RESTful servers; no DB required.

Jan 1, 2023
golang honeypot smtp server
golang honeypot smtp server

honeygogo-smtp standalone honeypot A lightweight SMTP honeypot server written in Go, leveraging go-smtp. A stand alone version of a module from honeyg

May 4, 2022
Simple SMTP Server for Testing

go-smtptester Simple SMTP Server for Testing. How it works All received mails are saved in a sync.Map with a key: From+Recipient1+Recipient2 Mails to

Nov 18, 2021
Web and API based SMTP testing
Web and API based SMTP testing

MailHog Inspired by MailCatcher, easier to install. Download and run MailHog Configure your outgoing SMTP server View your outgoing email in a web UI

Jan 4, 2023
Lightweight SMTP client written in Go

Hectane Hectane is both a Go package providing an SMTP queue for sending emails and a standalone application that exposes this functionality via an HT

Nov 23, 2022
MailHog SMTP Protocol

MailHog SMTP Protocol github.com/mailhog/smtp implements an SMTP server state machine. It attempts to encapsulate as much of the SMTP protocol (plus i

Oct 27, 2022
Simple tool to test SMTP mail send with various settings including TLS1.1 downgrade

smtptest Simple tool to test SMTP mail send with various settings including TLS1.1 downgrade All settings are configurable in the config.yaml file ser

Sep 19, 2022
Email 2.0 server
Email 2.0 server

RIGEL.Email Secure, fast and free email 2.0 server. Download latest version Linux, BSD, Mac OS X and Windows versions available. Supported fetures in

Jan 7, 2022
Robust and flexible email library for Go

email Robust and flexible email library for Go Email for humans The email package is designed to be simple to use, but flexible enough so as not to be

Dec 30, 2022
a simple api that sent spam via sms and email

a simple api that sent spam via sms and email routes: /sms /email example request with python

Oct 19, 2021
📮 Simple (but useful) email sender written in pure Go v1.17. Support HTML templates and attachments.

?? Go Email Sender Simple (but useful) email sender written in pure Go v1.17. Yes, yet another email package here! ?? Support HTML templates and attac

Dec 31, 2021
Monitoring and automation for Open Source email servers, starting with Postfix.
Monitoring and automation for Open Source email servers, starting with Postfix.

Welcome to Lightmeter Control Center, the Open Source mailops monitoring application.

Dec 19, 2022
:white_check_mark: A Go library for email verification without sending any emails.

email-verifier ✉️ A Go library for email verification without sending any emails. Features Email Address Validation: validates if a string contains a

Dec 30, 2022
An email MIME artist for golang

Marcel is a tool to generate IETF compliant emails in raw MIME format. I mainly use this for generating emails with attachments and sending them via amazon SES. If that's what you're doing too, you may want notifications

Nov 7, 2022