mirror of
https://github.com/nodemailer/wildduck.git
synced 2024-09-20 07:16:05 +08:00
Added example certififcates
This commit is contained in:
parent
eed456b745
commit
c42ab1519f
119
api.js
119
api.js
|
@ -7,13 +7,14 @@ const Joi = require('joi');
|
|||
const crypto = require('crypto');
|
||||
const tools = require('./lib/tools');
|
||||
const consts = require('./lib/consts');
|
||||
const mobileconfig = require('mobileconfig');
|
||||
const UserHandler = require('./lib/user-handler');
|
||||
const MailboxHandler = require('./lib/mailbox-handler');
|
||||
const MessageHandler = require('./lib/message-handler');
|
||||
const ImapNotifier = require('./lib/imap-notifier');
|
||||
const db = require('./lib/db');
|
||||
const MongoPaging = require('mongo-cursor-pagination');
|
||||
const certs = require('./lib/certs').get('api');
|
||||
const certs = require('./lib/certs');
|
||||
const ObjectID = require('mongodb').ObjectID;
|
||||
const imapTools = require('./imap-core/lib/imap-tools');
|
||||
const libmime = require('libmime');
|
||||
|
@ -23,6 +24,8 @@ const GridFSBucket = require('mongodb').GridFSBucket;
|
|||
const libbase64 = require('libbase64');
|
||||
const libqp = require('libqp');
|
||||
const urllib = require('url');
|
||||
const apiCerts = certs.get('api');
|
||||
const mobileconfigCerts = certs.get('api.mobileconfig');
|
||||
|
||||
const serverOptions = {
|
||||
name: 'Wild Duck API',
|
||||
|
@ -36,12 +39,12 @@ const serverOptions = {
|
|||
}
|
||||
};
|
||||
|
||||
if (certs && config.api.secure) {
|
||||
serverOptions.key = certs.key;
|
||||
if (certs.ca) {
|
||||
serverOptions.ca = certs.ca;
|
||||
if (apiCerts && config.api.secure) {
|
||||
serverOptions.key = apiCerts.key;
|
||||
if (apiCerts.ca) {
|
||||
serverOptions.ca = apiCerts.ca;
|
||||
}
|
||||
serverOptions.certificate = certs.cert;
|
||||
serverOptions.certificate = apiCerts.cert;
|
||||
}
|
||||
|
||||
const server = restify.createServer(serverOptions);
|
||||
|
@ -78,6 +81,20 @@ server.get(
|
|||
})
|
||||
);
|
||||
|
||||
server.use((req, res, next) => {
|
||||
if (config.api.accessToken && req.query.accessToken !== config.api.accessToken) {
|
||||
res.status(403);
|
||||
res.charSet('utf-8');
|
||||
return res.json({
|
||||
error: 'Invalid accessToken value'
|
||||
});
|
||||
}
|
||||
if (req.query.accessToken) {
|
||||
delete req.query.accessToken;
|
||||
}
|
||||
next();
|
||||
});
|
||||
|
||||
server.get({ name: 'users', path: '/users' }, (req, res, next) => {
|
||||
res.charSet('utf-8');
|
||||
|
||||
|
@ -662,6 +679,7 @@ server.put('/users/:user/addresses/:address', (req, res, next) => {
|
|||
}
|
||||
|
||||
if (!addressData || addressData.user.toString() !== user.toString()) {
|
||||
res.status(404);
|
||||
res.json({
|
||||
error: 'Invalid or unknown email address identifier'
|
||||
});
|
||||
|
@ -755,6 +773,7 @@ server.del('/users/:user/addresses/:address', (req, res, next) => {
|
|||
}
|
||||
|
||||
if (!addressData || addressData.user.toString() !== user.toString()) {
|
||||
res.status(404);
|
||||
res.json({
|
||||
error: 'Invalid or unknown email address identifier'
|
||||
});
|
||||
|
@ -1128,6 +1147,7 @@ server.get('/users/:user/addresses/:address', (req, res, next) => {
|
|||
return next();
|
||||
}
|
||||
if (!addressData) {
|
||||
res.status(404);
|
||||
res.json({
|
||||
error: 'Invalid or unknown address'
|
||||
});
|
||||
|
@ -2340,6 +2360,7 @@ server.del('/users/:user/mailboxes/:mailbox/messages/:message', (req, res, next)
|
|||
}
|
||||
|
||||
if (!messageData || messageData.user.toString() !== user.toString()) {
|
||||
res.status(404);
|
||||
res.json({
|
||||
error: 'Message was not found'
|
||||
});
|
||||
|
@ -2596,6 +2617,7 @@ server.del('/users/:user/filters/:filter', (req, res, next) => {
|
|||
}
|
||||
|
||||
if (!r.deletedCount) {
|
||||
res.status(404);
|
||||
res.json({
|
||||
error: 'Filter was not found'
|
||||
});
|
||||
|
@ -2953,6 +2975,7 @@ server.put('/users/:user/filters/:filter', (req, res, next) => {
|
|||
}
|
||||
|
||||
if (!r || !r.value || !r.value._id) {
|
||||
res.status(404);
|
||||
res.json({
|
||||
error: 'Filter was not found'
|
||||
});
|
||||
|
@ -3049,6 +3072,7 @@ server.post('/users/:user/asps', (req, res, next) => {
|
|||
user: Joi.string().hex().lowercase().length(24).required(),
|
||||
description: Joi.string().trim().max(255).required(),
|
||||
scopes: Joi.array().items(Joi.string().valid('imap', 'pop3', 'smtp', '*').required()).unique(),
|
||||
generateMobileconfig: Joi.boolean().truthy(['Y', 'true', 'yes', 1]).default(false),
|
||||
ip: Joi.string().ip({
|
||||
version: ['ipv4', 'ipv6'],
|
||||
cidr: 'forbidden'
|
||||
|
@ -3072,20 +3096,89 @@ server.post('/users/:user/asps', (req, res, next) => {
|
|||
}
|
||||
|
||||
let user = new ObjectID(result.value.user);
|
||||
let generateMobileconfig = result.value.generateMobileconfig;
|
||||
|
||||
userHandler.generateASP(user, result.value, (err, result) => {
|
||||
db.users.collection('users').findOne({
|
||||
_id: user
|
||||
}, {
|
||||
fields: {
|
||||
username: true,
|
||||
address: true
|
||||
}
|
||||
}, (err, userData) => {
|
||||
if (err) {
|
||||
res.json({
|
||||
error: err.message
|
||||
error: 'MongoDB Error: ' + err.message
|
||||
});
|
||||
return next();
|
||||
}
|
||||
res.json({
|
||||
success: true,
|
||||
id: result.id,
|
||||
password: result.password
|
||||
if (!userData) {
|
||||
res.json({
|
||||
error: 'This user does not exist'
|
||||
});
|
||||
return next();
|
||||
}
|
||||
|
||||
userHandler.generateASP(user, result.value, (err, result) => {
|
||||
if (err) {
|
||||
res.json({
|
||||
error: err.message
|
||||
});
|
||||
return next();
|
||||
}
|
||||
|
||||
if (!generateMobileconfig) {
|
||||
res.json({
|
||||
success: true,
|
||||
id: result.id,
|
||||
password: result.password
|
||||
});
|
||||
return next();
|
||||
}
|
||||
|
||||
let options = {
|
||||
displayName: config.name,
|
||||
displayDescription: 'Install this profile to auto configure your email account',
|
||||
emailAddress: userData.address,
|
||||
identifier: config.api.mobileconfig.identifier,
|
||||
imap: {
|
||||
hostname: config.imap.setup.hostname,
|
||||
port: config.imap.setup.port || config.imap.port,
|
||||
secure: config.imap.setup.secure,
|
||||
username: userData.username,
|
||||
password: result.password
|
||||
},
|
||||
smtp: {
|
||||
hostname: config.smtp.setup.hostname,
|
||||
port: config.smtp.setup.port || config.smtp.port,
|
||||
secure: true, //config.setup.smtp.secure,
|
||||
username: userData.username,
|
||||
password: false // use the same password as for IMAP
|
||||
},
|
||||
keys: mobileconfigCerts
|
||||
};
|
||||
|
||||
mobileconfig.getSignedEmailConfig(options, (err, data) => {
|
||||
if (err) {
|
||||
res.json({
|
||||
error: err.message
|
||||
});
|
||||
return next();
|
||||
}
|
||||
|
||||
//res.set('Content-Description', 'Mail App Configuration Profile');
|
||||
//res.set('Content-Type', 'application/x-apple-aspen-config');
|
||||
//res.set('Content-Disposition', util.format('attachment; filename="%s.mobileconfig"', req.user.username));
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
id: result.id,
|
||||
password: result.password,
|
||||
mobileconfig: data.toString('base64')
|
||||
});
|
||||
return next();
|
||||
});
|
||||
});
|
||||
return next();
|
||||
});
|
||||
});
|
||||
|
||||
|
|
19
certs/example.cert
Normal file
19
certs/example.cert
Normal file
|
@ -0,0 +1,19 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIIDBzCCAe+gAwIBAgIJAKtIcb4EW93NMA0GCSqGSIb3DQEBBQUAMBoxGDAWBgNV
|
||||
BAMMD3d3dy5leGFtcGxlLmNvbTAeFw0xNzA3MjUxMjI4MDNaFw0yNzA3MjMxMjI4
|
||||
MDNaMBoxGDAWBgNVBAMMD3d3dy5leGFtcGxlLmNvbTCCASIwDQYJKoZIhvcNAQEB
|
||||
BQADggEPADCCAQoCggEBAMDEaQZGMZ6mZsaELGKroi+q8USSH4UpkpSz6jVxNecC
|
||||
pTjf+UlAOKLaISj1ZIP0vTMFPrwuhhvmsBTSALfrOVCAOF963BzdHIuR173PS/wb
|
||||
ehLgftvqGme/8FYW61eSPeYmH9IXyPEfpN0SWU1n2Blh1KDX4UuCpwnkXuKYm6uN
|
||||
9qfyvV7HVwXSVlvBcruScTytbjuBYld6007Bf0ofxZipYB7hH2yo2Kivih9j3EGx
|
||||
9whzjub3Yh5rwxQiUBtAekIAFgWL+n69pnH/3VDB7+ha3eXmZF3LXlR6QQHz2Q9c
|
||||
6ZkDqfpyQ/aPWKD0gNMHzzf91/7Ag6B62LVJIjdpwUcCAwEAAaNQME4wHQYDVR0O
|
||||
BBYEFN64rpadgDmLHi3wAva7mjUNS49XMB8GA1UdIwQYMBaAFN64rpadgDmLHi3w
|
||||
Ava7mjUNS49XMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAAszJ8h8
|
||||
uDz9SpNDB2jeOLsuo/uhag2JxaK+WBH/hksHHRWm/b7YgmPO7tuzDB0poJ9Mgfai
|
||||
gGKkpStccZjyESOKZSfLGe2+fuAuLJ8eKYiQqZNwrD1rykjT9FGQzh4GODHHbnjc
|
||||
UsyXJRa1P0J+7kybOhULuOmks3HODoSCarD8ns3/D+aemtfrr2dLptuC+uzk54Kb
|
||||
TYis6JZimhwMQX8Sfms9ehLvh/oGcxAONF2lYLkwqjNQahvNAHQQZx5CnzDlk2Wb
|
||||
g+/CZisGQimIiwrY+QCL+dJKA4yLO00yrB/1N5zt7+Y068EVUNx8ZrA5kOHZXmuC
|
||||
0k20kdIqlumBXtk=
|
||||
-----END CERTIFICATE-----
|
27
certs/example.key
Normal file
27
certs/example.key
Normal file
|
@ -0,0 +1,27 @@
|
|||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEowIBAAKCAQEAwMRpBkYxnqZmxoQsYquiL6rxRJIfhSmSlLPqNXE15wKlON/5
|
||||
SUA4otohKPVkg/S9MwU+vC6GG+awFNIAt+s5UIA4X3rcHN0ci5HXvc9L/Bt6EuB+
|
||||
2+oaZ7/wVhbrV5I95iYf0hfI8R+k3RJZTWfYGWHUoNfhS4KnCeRe4pibq432p/K9
|
||||
XsdXBdJWW8Fyu5JxPK1uO4FiV3rTTsF/Sh/FmKlgHuEfbKjYqK+KH2PcQbH3CHOO
|
||||
5vdiHmvDFCJQG0B6QgAWBYv6fr2mcf/dUMHv6Frd5eZkXcteVHpBAfPZD1zpmQOp
|
||||
+nJD9o9YoPSA0wfPN/3X/sCDoHrYtUkiN2nBRwIDAQABAoIBAAJHkFJhrB6LKzX3
|
||||
xCqaiv1zUQ0ViUfi2PfnNMLTBucncdq9U05ZcxIB8FhypnClCUO8MSS6jB1yWey1
|
||||
GwsRvgjEq2X9pvK0bqz72YhGFkjx7jyg6P8iwpMtguMRvFC5yv+YvdGXNGodjK6M
|
||||
k//FVZnfPUt1ohVpgx4r1C9rzJN3wgyl0Wfi9tclu5t4+tRGarjImVl0RvyTlNG1
|
||||
+grKLhBVvfx19S9Dop57X1JfSW1VCq3wzf+ztnZa+nSKUz/nJmMZ/WPAs0xQC6Jg
|
||||
eHwl+dhw6hOq7K1NXZfodHUD538Oyn//r2HCSth37pavxfqUJQM4uoqMSMY8JNQF
|
||||
Uv/NtoECgYEA4sq0pLZPRKCEcVhi6vyt0CgqINL5YhMgJgyrfJfI8Fb0BgoMoD66
|
||||
cChUcXE9Ep3oittu3b3H7/ou0Vb9Qy1ZjXPLFLFmy0U9xDNWX6dM/alsy2aGaRzX
|
||||
uYEuWjY0HkO9bEd6MLTRI5tKTOIBkdOtgpUu/iSsSijCvbMZa8UcLkECgYEA2Zfr
|
||||
KuxkrEoHSV0F53R9PUGpPttGyCkUhIguiTcONd8BjOJPKeIEP4CwYm01Ds2VOk2P
|
||||
cpACzEwPwK4FvT8Hh/la1H1n5JFAerbdZaybmJc0lxhQV6tNMhzxRcYDm21i2zMW
|
||||
EL5OBAccZbg5Eo5XdiK6cwe4nl/2g/8pwqBQHYcCgYAybTf1V8QQUlCgkzKLZVuQ
|
||||
aR3U5pQkxnPjgfWvYmB/cBYaManVB52UyqLcBn254fqOxXPFQilupoY6bckqYq8C
|
||||
0LhbBYcBs4ekVHXkFuL7k+xo3YcNYChnSt3vmRXFlPJNXSdCJTJLZIAE0EvhDNwL
|
||||
qPgl8imM47tJSsVgPRejAQKBgCXptX0OIWBvqaNbxPqWLngs56tfE48usTeCbvFT
|
||||
mXNDfwaoK/j1O55A8vrDYnpI0daNyw/ADezA2AHPkIpv4AUOKohZrW+C64Q2No9P
|
||||
qvDEb9Jf1yffXhz8NAHfRaOgRJhC53ZVYkyLXKRQnAkiqhSYano+fymBOPe4zvLt
|
||||
cegjAoGBANBY+cOuX4k8msGkyRpDQR2e2yjUZ6MvDRmlEi7xzokAoM4OvYhmX2CP
|
||||
wkagMotxYHn0kpe/xRqGb/rkpsjDWPhVyBHOF3/ZAFAeyt4Y2OuvWQ2K0YyBWiED
|
||||
/wRp7I3V3oHB/i/gnokEo7u4ty/yPB8qsTwe4zcYoDn78C1q/IGl
|
||||
-----END RSA PRIVATE KEY-----
|
|
@ -6,6 +6,8 @@
|
|||
# process title and syslog ident
|
||||
ident="wildduck"
|
||||
|
||||
name="Wild Duck Mail"
|
||||
|
||||
# how many processes to start
|
||||
processes=1
|
||||
|
||||
|
@ -77,6 +79,13 @@ maxForwards=2000
|
|||
# if `true` then do not autodelete expired messages
|
||||
disableRetention=false
|
||||
|
||||
[imap.setup]
|
||||
# Public configuration for IMAP
|
||||
hostname="localtest.me"
|
||||
secure=true
|
||||
# port defaults to imap.port
|
||||
#port=9993
|
||||
|
||||
[tls]
|
||||
# Default TLS keys (can be overriden by individual services)
|
||||
#key="/path/to/server/key.pem"
|
||||
|
@ -123,6 +132,13 @@ maxForwards=2000
|
|||
#key="/path/to/server/key.pem"
|
||||
#cert="/path/to/server/cert.pem"
|
||||
|
||||
[pop3.setup]
|
||||
# Public configuration for POP3
|
||||
hostname="localtest.me"
|
||||
secure=true
|
||||
# port defaults to pop3.port
|
||||
#port=9995
|
||||
|
||||
[api]
|
||||
enabled=true
|
||||
port=8080
|
||||
|
@ -130,13 +146,25 @@ maxForwards=2000
|
|||
host="127.0.0.1"
|
||||
|
||||
# Use `true` (HTTPS) for port 443 and `false` (HTTP) for 80
|
||||
secure=true
|
||||
secure=false
|
||||
|
||||
# If set requires all API calls to have accessToken query argument with that value
|
||||
# http://localhost:8080/users?accessToken=somesecretvalue
|
||||
#accessToken="somesecretvalue"
|
||||
|
||||
[api.tls]
|
||||
# If certificate path is not defined, use global or built-in self-signed certs
|
||||
#key="/path/to/server/key.pem"
|
||||
#cert="/path/to/server/cert.pem"
|
||||
|
||||
[api.mobileconfig]
|
||||
identifier="com.email.wildduck"
|
||||
|
||||
[api.mobileconfig.tls]
|
||||
# If certificate path is not defined, use global or built-in self-signed certs
|
||||
#key="/path/to/server/key.pem"
|
||||
#cert="/path/to/server/cert.pem"
|
||||
|
||||
[sender]
|
||||
# Push messages to ZoneMTA queue for delivery
|
||||
# if `false` then no messages are sent
|
||||
|
@ -152,3 +180,9 @@ maxForwards=2000
|
|||
# see [dbs].sender option for choosing correct database to use for ZoneMTA queues
|
||||
# by default the main wildduck database is used
|
||||
collection="zone-queue"
|
||||
|
||||
[smtp.setup]
|
||||
# Public configuration for SMTP MDA
|
||||
hostname="localtest.me"
|
||||
secure=false
|
||||
port=2587
|
||||
|
|
113
docs/api.md
113
docs/api.md
|
@ -2,89 +2,111 @@
|
|||
|
||||
Wild Duck Mail Server is a scalable IMAP / POP3 server that natively exposes internal data through an HTTP API.
|
||||
|
||||
This API is not meant to be used by end users but your application.
|
||||
|
||||
- [API Usage Info](#api-usage-info)
|
||||
* [Responses](#responses)
|
||||
* [Paging](#paging)
|
||||
- [Users](#users)
|
||||
* [Search and list users](#search-and-list-users)
|
||||
+ [GET /users](#get--users)
|
||||
+ [GET /users](#get-users)
|
||||
* [Get one user](#get-one-user)
|
||||
+ [GET /users/{user}](#get--users--user-)
|
||||
+ [GET /users/{user}](#get-users-user-)
|
||||
* [Add a new user](#add-a-new-user)
|
||||
+ [POST /users](#post--users)
|
||||
+ [POST /users](#post-users)
|
||||
* [Update user details](#update-user-details)
|
||||
+ [PUT /users/{user}](#put--users--user-)
|
||||
- [Authentication](#authentication)
|
||||
* [Authenticate an user](#authenticate-an-user)
|
||||
+ [POST /authenticate](#post--authenticate)
|
||||
+ [POST /authenticate](#post-authenticate)
|
||||
* [List the authentication log](#list-the-authentication-log)
|
||||
+ [GET /users/{user}/authlog](#get--users--user--authlog)
|
||||
+ [GET /users/{user}/authlog](#get-users-user-authlog)
|
||||
- [2FA](#2fa)
|
||||
* [Setup 2FA](#setup-2fa)
|
||||
+ [POST /users/{user}/2fa](#post--users--user--2fa)
|
||||
+ [POST /users/{user}/2fa](#post-users-user-2fa)
|
||||
* [Verify 2FA](#verify-2fa)
|
||||
+ [PUT /users/{user}/2fa](#put--users--user--2fa)
|
||||
+ [PUT /users/{user}/2fa](#put-users-user-2fa)
|
||||
* [Disable 2FA](#disable-2fa)
|
||||
+ [DELETE /users/{user}/2fa](#delete--users--user--2fa)
|
||||
+ [DELETE /users/{user}/2fa](#delete-users-user-2fa)
|
||||
* [Check 2FA](#check-2fa)
|
||||
+ [GET /users/{user}/2fa](#get--users--user--2fa)
|
||||
+ [GET /users/{user}/2fa](#get-users-user-2fa)
|
||||
- [Application Specific Passwords](#application-specific-passwords)
|
||||
* [List existing passwords](#list-existing-passwords)
|
||||
+ [GET /user/{user}/asps](#get--user--user--asps)
|
||||
+ [GET /user/{user}/asps](#get-user-user-asps)
|
||||
* [Add a new Application Specific Password](#add-a-new-application-specific-password)
|
||||
+ [POST /users/{user}/asps](#post--users--user--asps)
|
||||
+ [POST /users/{user}/asps](#post-users-user-asps)
|
||||
* [Delete an Application Specific Password](#delete-an-application-specific-password)
|
||||
+ [DELETE /users/{user}/asps/{asp}](#delete--users--user--asps--asp-)
|
||||
+ [DELETE /users/{user}/asps/{asp}](#delete-users-user-asps-asp-)
|
||||
- [Addresses](#addresses)
|
||||
* [Search and list addresses](#search-and-list-addresses)
|
||||
+ [GET /addresses](#get--addresses)
|
||||
+ [GET /addresses](#get-addresses)
|
||||
* [List user addresses](#list-user-addresses)
|
||||
+ [GET /users/{user}/addresses](#get--users--user--addresses)
|
||||
+ [GET /users/{user}/addresses](#get-users-user-addresses)
|
||||
* [Get one address](#get-one-address)
|
||||
+ [GET /users/{user}/addresses/{address}](#get--users--user--addresses--address-)
|
||||
+ [GET /users/{user}/addresses/{address}](#get-users-user-addresses-address-)
|
||||
* [Add a new address](#add-a-new-address)
|
||||
+ [POST /users/{user}/addresses](#post--users--user--addresses)
|
||||
+ [POST /users/{user}/addresses](#post-users-user-addresses)
|
||||
* [Update address details](#update-address-details)
|
||||
+ [PUT /users/{user}/addresses/{address}](#put--users--user--addresses--address-)
|
||||
+ [PUT /users/{user}/addresses/{address}](#put-users-user-addresses-address-)
|
||||
* [Delete an alias address](#delete-an-alias-address)
|
||||
+ [DELETE /users/{user}/addresses/{address}](#delete--users--user--addresses--address-)
|
||||
+ [DELETE /users/{user}/addresses/{address}](#delete-users-user-addresses-address-)
|
||||
- [Mailboxes](#mailboxes)
|
||||
* [List existing mailboxes](#list-existing-mailboxes)
|
||||
+ [GET /user/{user}/mailboxes](#get--user--user--mailboxes)
|
||||
+ [GET /user/{user}/mailboxes](#get-user-user-mailboxes)
|
||||
* [Get one mailbox](#get-one-mailbox)
|
||||
+ [GET /users/{user}/mailboxes/{mailbox}](#get--users--user--mailboxes--mailbox-)
|
||||
+ [GET /users/{user}/mailboxes/{mailbox}](#get-users-user-mailboxes-mailbox-)
|
||||
* [Add a new mailbox](#add-a-new-mailbox)
|
||||
+ [POST /users/{user}/mailboxes](#post--users--user--mailboxes)
|
||||
+ [POST /users/{user}/mailboxes](#post-users-user-mailboxes)
|
||||
* [Update mailbox details](#update-mailbox-details)
|
||||
+ [PUT /users/{user}/mailboxes/{mailbox}](#put--users--user--mailboxes--mailbox-)
|
||||
+ [PUT /users/{user}/mailboxes/{mailbox}](#put-users-user-mailboxes-mailbox-)
|
||||
* [Delete a mailbox](#delete-a-mailbox)
|
||||
+ [DELETE /users/{user}/mailboxes/{mailbox}](#delete--users--user--mailboxes--mailbox-)
|
||||
+ [DELETE /users/{user}/mailboxes/{mailbox}](#delete-users-user-mailboxes-mailbox-)
|
||||
- [Messages](#messages)
|
||||
* [List existing messages](#list-existing-messages)
|
||||
+ [GET /user/{user}/mailboxes/{mailbox}/messages](#get--user--user--mailboxes--mailbox--messages)
|
||||
+ [GET /user/{user}/mailboxes/{mailbox}/messages](#get-user-user-mailboxes-mailbox-messages)
|
||||
* [Search for messages](#search-for-messages)
|
||||
+ [GET /user/{user}/search](#get--user--user--search)
|
||||
+ [GET /user/{user}/search](#get-user-user-search)
|
||||
* [Get message details](#get-message-details)
|
||||
+ [GET /users/{user}/mailboxes/{mailbox}/messages/{message}](#get--users--user--mailboxes--mailbox--messages--message-)
|
||||
+ [GET /users/{user}/mailboxes/{mailbox}/messages/{message}](#get-users-user-mailboxes-mailbox-messages-message-)
|
||||
* [Update message details](#update-message-details)
|
||||
+ [PUT /users/{user}/mailboxes/{mailbox}/messages/{message}](#put--users--user--mailboxes--mailbox--messages--message-)
|
||||
+ [PUT /users/{user}/mailboxes/{mailbox}/messages/{message}](#put-users-user-mailboxes-mailbox-messages-message-)
|
||||
* [Delete a message](#delete-a-message)
|
||||
+ [DELETE /users/{user}/mailboxes/{mailbox}/messages/{message}](#delete--users--user--mailboxes--mailbox--messages--message-)
|
||||
+ [DELETE /users/{user}/mailboxes/{mailbox}/messages/{message}](#delete-users-user-mailboxes-mailbox-messages-message-)
|
||||
* [Get message source](#get-message-source)
|
||||
+ [GET /users/{user}/mailboxes/{mailbox}/messages/{message}/message.eml](#get--users--user--mailboxes--mailbox--messages--message--messageeml)
|
||||
+ [GET /users/{user}/mailboxes/{mailbox}/messages/{message}/message.eml](#get-users-user-mailboxes-mailbox-messages-message-messageeml)
|
||||
* [Get message attachment](#get-message-attachment)
|
||||
+ [GET /users/{user}/mailboxes/{mailbox}/messages/{message}/attachments/{attachment}](#get--users--user--mailboxes--mailbox--messages--message--attachments--attachment-)
|
||||
+ [GET /users/{user}/mailboxes/{mailbox}/messages/{message}/attachments/{attachment}](#get-users-user-mailboxes-mailbox-messages-message-attachments-attachment-)
|
||||
- [Filters](#filters)
|
||||
* [Create new filter](#create-new-filter)
|
||||
+ [POST /users/{user}/filters](#post-users-user-filters)
|
||||
* [List existing filters](#list-existing-filters)
|
||||
+ [GET /user/{user}/filters](#get-user-user-filters)
|
||||
* [Get filter details](#get-filter-details)
|
||||
+ [GET /users/{user}/filters/{filter}](#get-users-user-filters-filter-)
|
||||
* [Update filter details](#update-filter-details)
|
||||
+ [PUT /users/{user}/filters/{filter}](#put-users-user-filters-filter-)
|
||||
* [Delete a filter](#delete-a-filter)
|
||||
+ [DELETE /users/{user}/filters/{filter}](#delete-users-user-filters-filter-)
|
||||
- [Quota](#quota)
|
||||
* [Recalculate user quota](#recalculate-user-quota)
|
||||
+ [POST /users/{user}/quota/reset](#post--users--user--quota-reset)
|
||||
+ [POST /users/{user}/quota/reset](#post-users-user-quota-reset)
|
||||
- [Updates](#updates)
|
||||
* [Stream update events](#stream-update-events)
|
||||
+ [GET /users/{user}/updates](#get--users--user--updates)
|
||||
+ [GET /users/{user}/updates](#get-users-user-updates)
|
||||
|
||||
<small><i><a href='http://ecotrust-canada.github.io/markdown-toc/'>Table of contents generated with markdown-toc</a></i></small>
|
||||
|
||||
## API Usage Info
|
||||
|
||||
### Authentication
|
||||
|
||||
This API should be used by your application and not by the end users directly, so normally it should probably be hidden behind a firewall.
|
||||
|
||||
To add another layer of protection the API can be set to require an access token. The token value can be set in configuration file "api.accessToken". If the value is set, then all requests against the API must include a query argument *accessToken* with the same value as in the configuration file.
|
||||
|
||||
```
|
||||
curl "http://localhost:8080/users?query=testuser01&accessToken=secrettoken"
|
||||
```
|
||||
|
||||
### Responses
|
||||
|
||||
All successful responses look like the following:
|
||||
|
@ -581,6 +603,7 @@ Creates a new Application Specific Password for an existing user, returns the ID
|
|||
- **user** (required) is the ID of the user
|
||||
- **description** (required) is the name or description for the new Application Specific Password
|
||||
- **scopes** is an array of scopes this password is valid for. Valid scopes are "imap", "pop3", "smtp" or "*" for all ASP supported scopes
|
||||
- **generateMobileconfig** is a boolean. If true, then the result includes a base64 formatted profile file to autoconfigure OSX and iOS mail clients
|
||||
- **ip** is the IP address the request was made from
|
||||
|
||||
**Example**
|
||||
|
@ -603,7 +626,29 @@ Response for a successful operation:
|
|||
}
|
||||
```
|
||||
|
||||
Resulting password should be shown to the client. This password is shown only once so if the user forgets it then the APS should be deleted and replaced with a new one.
|
||||
Or with the profile file
|
||||
|
||||
```
|
||||
curl -XPOST "http://localhost:8080/users/5971da1754cfdc7f0983b2ec/asps" -H 'content-type: application/json' -d '{
|
||||
"description": "Mac OSX Mail Client",
|
||||
"scopes": ["imap"],
|
||||
"generateMobileconfig": true
|
||||
"ip": "192.168.10.10"
|
||||
}'
|
||||
```
|
||||
|
||||
and the result:
|
||||
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"id": "59773be3a7bc855155286d91",
|
||||
"password": "slrfwaavyzmatgxf",
|
||||
"mobileconfig": "MIIO8gYJKoZIhvcNAQcCo..."
|
||||
}
|
||||
```
|
||||
|
||||
Resulting password should be shown to the client. This password is shown only once so if the user forgets it then the APS should be deleted and replaced with a new one. Mobileconfig file should be sent to the client with Content-Type value of `application/x-apple-aspen-config`.
|
||||
|
||||
### Delete an Application Specific Password
|
||||
|
||||
|
|
28
lib/certs.js
28
lib/certs.js
|
@ -6,8 +6,24 @@ const fs = require('fs');
|
|||
const certs = new Map();
|
||||
|
||||
// load certificate files
|
||||
[false, 'imap', 'lmtp', 'pop3', 'api'].forEach(type => {
|
||||
let tlsconf = type ? config[type] && config[type].tls : config.tls;
|
||||
[false, 'imap', 'lmtp', 'pop3', 'api', 'api.mobileconfig'].forEach(type => {
|
||||
let tlsconf = config.tls;
|
||||
|
||||
if (type) {
|
||||
let path = (type + '.tls').split('.');
|
||||
tlsconf = config;
|
||||
for (let i = 0; i < path.length; i++) {
|
||||
let key = path[i];
|
||||
if (!tlsconf[key]) {
|
||||
tlsconf = false;
|
||||
break;
|
||||
}
|
||||
tlsconf = tlsconf[key];
|
||||
}
|
||||
if (!tlsconf || !tlsconf.key) {
|
||||
tlsconf = config.tls;
|
||||
}
|
||||
}
|
||||
|
||||
if (!tlsconf) {
|
||||
return;
|
||||
|
@ -41,4 +57,12 @@ const certs = new Map();
|
|||
});
|
||||
});
|
||||
|
||||
if (!certs.has('default')) {
|
||||
certs.set('default', {
|
||||
key: fs.readFileSync(__dirname + '/../certs/example.key', 'ascii'),
|
||||
cert: fs.readFileSync(__dirname + '/../certs/example.cert', 'ascii'),
|
||||
ca: false
|
||||
});
|
||||
}
|
||||
|
||||
module.exports.get = type => (certs.has(type) ? certs.get(type) : certs.get('default')) || false;
|
||||
|
|
Loading…
Reference in a new issue