The goal of the document is to allow anyone to start a James instance as an operational mail server.
The two methods described bellow should not be used in production.
First method, from James source code:
Step 0: Requirements #################### * Java 11 SDK * 2GB RAM * Docker 1.7.1+ * Maven 3.3 Step 1: Download ################# * Clone the James git repository $ git clone git://git.apache.org/james-project.git Step 3: Compile ############### * Compile the Guice Cassandra project $ mvn package -DskipTests --also-make --projects server/container/guice/cassandra-guice * Compile the James CLI project $ mvn package -DskipTests -am -pl server/container/cli Step 3: Deploy ############## 3.1. Deploy Cassandra (optional) You may skip this part if you already have a running Cassandra on your network. $ docker run --detach=true --name=cassandra cassandra:4.1.3 3.2. Deploy OpenSearch (optional) You may skip this part if you already have a running OpenSearch on your network. $ docker run -d --network james -p 9200:9200 --name=opensearch --env 'discovery.type=single-node' opensearchproject/opensearch:2.1.0 Step 4: Configure ################# * Follow the Cassandra guice configuration documentation. * We need to provide the key we will use for TLS. For obvious reasons, this is not provided in this git. Copy your TLS keys to ./conf/keystore or generate it using : $ keytool -genkey -alias james -keyalg RSA -keystore ./conf/keystore You will have to put the keystore password in the right xml files (imapserver.xml, pop3server.xml, smtpserver.xml) You are welcome to use the default configuration which can be found in the $PWD/server/apps/cassandra-app/sample-configuration folder. Step 5: Start ############# * Run James $ sudo java -Dworking.directory=WORKING_PATH -jar server/container/guice/cassandra-guice/target/james-server-cassandra-guice.jar Where : - WORKING_PATH is the path of the folder which contains your configuration files. You have to run this command with the superuser, has some default ports are lower than 1000 (default imap, smtp...). You may get rid of that by overriding the default configuration Step 6: Create Domains and Users ################################ Time to add domains and users. $ java -jar server/container/cli/target/james-server-cli.jar -h 127.0.0.1 -p 9999 adddomain DOMAIN $ java -jar server/container/cli/target/james-server-cli.jar -h 127.0.0.1 -p 9999 adduser USER_MAIL_ADDRESS PASSWORD Where : - DOMAIN is the domain you want to handle with this server - USER_MAIL_ADDRESS user's email - PASSWORD user's password Step 7: Test ############And for IMAP (SSL):$ telnet HOSTNAME 25 Trying HOSTNAME... Connected to HOSTNAME. Escape character is '^]'. 220 172.16.1.131 SMTP Server (JAMES SMTP Server 3.0.0) ready Wed, 20 Jul 2017 17:31:33 +0100 (CET) ehlo test 250-172.16.1.131 Hello test (aoscommunity.com [127.0.0.1]) 250-PIPELINING 250-ENHANCEDSTATUSCODES 250 8BITMIME mail from:<YOUR_NAME@YOUR_DOMAIN> 250 2.1.0 Sender <YOUR_NAME@YOUR_DOMAIN> OK rcpt to:<YOUR_NAME@YOUR_DOMAIN> 250 2.1.5 Recipient <YOUR_NAME@YOUR_DOMAIN> OK data 354 Ok Send data ending with <CRLF>.<CRLF> subject: test this is a test . 250 2.6.0 Message received quit Connection closed by foreign host.Step 8: Manage ############## 8.1. Manage via james-cli usage: $ java -jar server/container/cli/target/james-server-cli.jar -h 127.0.0.1 -p 9999 Available commands: adduser </username> </password> removeuser </username> listusers adddomain </domainname> removedomain </domainname> listdomains 8.2. Manage via JMX * Launch jconsole (or any other JMX client) and connect on URL=service:jmx:rmi:///jndi/rmi://localhost:HOSTNAME/jmxrmi * Select the MBeans tab and open the org.apache.james node to view attributes and execute operations. Step 9: Monitor ############### * Monitor the ./log/james-server.log log file. * Monitor via JMX (launch any JMX client and connect to URL=service:jmx:rmi:///jndi/rmi://HOSTNAME:9999/jmxrmi) * Check ./var folder usage mail +-error +-address-error +-relay-denied +-spam store +-derby +-jackrabbit +-activemq +-brokers +-james +-blob-transfer +-outgoing +-spool * Check /tmp folder usage$ openssl s_client -connect 127.0.0.1:993 CONNECTED(00000003) Can't use SSL_get_servername depth=0 C = FR, ST = Unknown, L = Puteaux, O = James, OU = Linagora, CN = Benoit Tellier verify error:num=18:self signed certificate verify return:1 depth=0 C = FR, ST = Unknown, L = Puteaux, O = James, OU = Linagora, CN = Benoit Tellier verify error:num=10:certificate has expired notAfter=Nov 24 07:32:55 2015 GMT verify return:1 depth=0 C = FR, ST = Unknown, L = Puteaux, O = James, OU = Linagora, CN = Benoit Tellier notAfter=Nov 24 07:32:55 2015 GMT verify return:1 --- Certificate chain 0 s:C = FR, ST = Unknown, L = Puteaux, O = James, OU = Linagora, CN = Benoit Tellier i:C = FR, ST = Unknown, L = Puteaux, O = James, OU = Linagora, CN = Benoit Tellier --- Server certificate -----BEGIN CERTIFICATE----- MIIDeTCCAmGgAwIBAgIEXaLC/zANBgkqhkiG9w0BAQsFADBtMQswCQYDVQQGEwJG UjEQMA4GA1UECBMHVW5rbm93bjEQMA4GA1UEBxMHUHV0ZWF1eDEOMAwGA1UEChMF SmFtZXMxETAPBgNVBAsTCExpbmFnb3JhMRcwFQYDVQQDEw5CZW5vaXQgVGVsbGll cjAeFw0xNTA4MjYwNzMyNTVaFw0xNTExMjQwNzMyNTVaMG0xCzAJBgNVBAYTAkZS MRAwDgYDVQQIEwdVbmtub3duMRAwDgYDVQQHEwdQdXRlYXV4MQ4wDAYDVQQKEwVK YW1lczERMA8GA1UECxMITGluYWdvcmExFzAVBgNVBAMTDkJlbm9pdCBUZWxsaWVy MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAhW0GWSgkK44XQpwLn8KX q9kJ3zgDYllEX7W8p+3sBYMAP0JC+lzh42mX/8XHti0vkmv/vjk0paAsB9s5uYhv /W94sdqjexi3L213+OD5Kcy+2tTgXN1ucF65d/dDeqGHAyBs1rm6LgyRwQ5ye8Cl OtXbSkz5qujmnFDDzrDIgzefxFsTHHIBTsdyttq2Atqzgdg2LHaFbIntwr6lfl9v puXr8p+CY6PfehX8mdmaJ7J/gfAll3zzdgeNUoAW0eDvcsphJ06elsDahieo0n/o XVhy+TGWtAQRDZQDjeK2BX/vVSPAlGOW7hVTv7WycAolzKlXZyiJMnwTWJl6YoUP vQIDAQABoyEwHzAdBgNVHQ4EFgQU7tDLswRlOJqoX4aVgrXRQbmOYbIwDQYJKoZI hvcNAQELBQADggEBAGmzK2i2H5D6xITyN1iNQhXbABQ/3rz9K5dEvy0ZLgYOUqyw 1WD43Do/A3eZuEZbuuYAlbvDEUNgS7rJ5HCrwIKFbPHWmfRX2j59UX+R8fI6G9wB qqcRYWpert347rGT/7MFLHk55LL6Tf//fwoWu6GWRj3wTvosVuunUiiC6zTS4MN9 moJp+IF03Q6JOPWu7/tfaKfXQHxG/hK492oV2vBG2r29UUJW6YO1S0DK+/cU0cCu +jqbY1ZOIAk906onRUFoPGuypOm3vmbE6mo5o49rNtp+VmZagZ7GsjJ4KWJB1c6d SFNIFlH2VlS8Lywr2tesClWO5tqtMswRsoA9GeU= -----END CERTIFICATE----- subject=C = FR, ST = Unknown, L = Puteaux, O = James, OU = Linagora, CN = Benoit Tellier issuer=C = FR, ST = Unknown, L = Puteaux, O = James, OU = Linagora, CN = Benoit Tellier --- No client certificate CA names sent Peer signing digest: SHA256 Peer signature type: RSA-PSS Server Temp Key: X25519, 253 bits --- SSL handshake has read 1425 bytes and written 363 bytes Verification error: certificate has expired --- New, TLSv1.3, Cipher is TLS_AES_256_GCM_SHA384 Server public key is 2048 bit Secure Renegotiation IS NOT supported Compression: NONE Expansion: NONE No ALPN negotiated Early data was not sent Verify return code: 10 (certificate has expired) --- --- Post-Handshake New Session Ticket arrived: SSL-Session: Protocol : TLSv1.3 Cipher : TLS_AES_256_GCM_SHA384 Session-ID: 92D136BF8C9E3E09C4FF7946A2AFDC8ED6E395A1729532D3544E58F688B787F9 Session-ID-ctx: Resumption PSK: C4E09FF3045720EE910AEA5300D87FDE2200A56F218AC3F75748BE794F73F32790FC8DD35CA70869FBD075727779BA73 PSK identity: None PSK identity hint: None SRP username: None TLS session ticket lifetime hint: 86400 (seconds) TLS session ticket: 0000 - 03 d2 89 8a 32 48 28 a2-99 24 99 47 b2 05 e8 99 ....2H(..$.G.... 0010 - 6b 9b a9 0b 59 95 dd 2c-fb ba 46 b9 94 ad 36 63 k...Y..,..F...6c Start Time: 1630033038 Timeout : 7200 (sec) Verify return code: 10 (certificate has expired) Extended master secret: no Max Early Data: 0 --- read R BLOCK * OK JAMES IMAP4rev1 Server 2e73ecd482f4 is ready. a login bob@domain.com 1234 a OK LOGIN completed. 1 logout * BYE IMAP4rev1 Server logging out 1 OK LOGOUT completed. closed
Second method, with docker-compose:
Step 0: Requirements #################### * 2GB RAM * Docker 1.7.1+ * wget Step 1: Download ################# * Get the James docker-compose file $ wget https://raw.githubusercontent.com/apache/james-project/master/server/apps/distributed-app/docker-compose.yml Step 2: Start ############# * Run James $ docker-compose up Step 3: Create Domains and Users ################################ Time to add domains and users. $ docker exec james java -jar /root/james-cli.jar -h 127.0.0.1 -p 9999 adddomain DOMAIN $ docker exec james java -jar /root/james-cli.jar -h 127.0.0.1 -p 9999 adduser USER_MAIL_ADDRESS PASSWORD Where : - DOMAIN is the domain you want to handle with this server - USER_MAIL_ADDRESS user's email - PASSWORD user's password Step 4: Test ############ $ telnet HOSTNAME 25 Trying HOSTNAME... Connected to HOSTNAME. Escape character is '^]'. 220 172.16.1.131 SMTP Server (JAMES SMTP Server 3.0.0) ready Wed, 20 Jul 2017 17:31:33 +0100 (CET) ehlo test 250-172.16.1.131 Hello test (aoscommunity.com [127.0.0.1]) 250-PIPELINING 250-ENHANCEDSTATUSCODES 250 8BITMIME mail from:<YOUR_NAME@YOUR_DOMAIN> 250 2.1.0 Sender <YOUR_NAME@YOUR_DOMAIN> OK rcpt to:<YOUR_NAME@YOUR_DOMAIN> 250 2.1.5 Recipient <YOUR_NAME@YOUR_DOMAIN> OK data 354 Ok Send data ending with <CRLF>.<CRLF> subject: test this is a test . 250 2.6.0 Message received quit Connection closed by foreign host. Step 5: Manage ############## 5.1. Manage via james-cli usage: $ docker exec james java -jar /root/james-cli.jar -h 127.0.0.1 -p 9999 Available commands: adduser </username> </password> removeuser </username> listusers adddomain </domainname> removedomain </domainname> listdomains 5.2. Manage via JMX * Launch jconsole (or any other JMX client) and connect on URL=service:jmx:rmi:///jndi/rmi://localhost:HOSTNAME/jmxrmi * Select the MBeans tab and open the org.apache.james node to view attributes and execute operations. Step 6: Monitor ############### * Monitor the ./log/james-server.log log file. * Monitor via JMX (launch any JMX client and connect to URL=service:jmx:rmi:///jndi/rmi://HOSTNAME:9999/jmxrmi) * Check ./var folder usage mail +-error +-address-error +-relay-denied +-spam store +-derby +-jackrabbit +-activemq +-brokers +-james +-blob-transfer +-outgoing +-spool * Check /tmp folder usage