Add SMTP notifier as an available option in configuration
One can now plug its own SMTP server to send notifications for identity validation and password reset requests. Filesystem has been removed from the template configuration file since even tests now use mail catcher (the fake webmail) to retrieve the email and the confirmation link.pull/97/head
parent
7a2b45a66f
commit
4cd78f3f83
|
@ -29,3 +29,5 @@ dist/
|
||||||
|
|
||||||
# Specific files
|
# Specific files
|
||||||
/config.yml
|
/config.yml
|
||||||
|
|
||||||
|
example/ldap/private.ldif
|
||||||
|
|
25
README.md
25
README.md
|
@ -39,14 +39,15 @@ as 2nd factor.
|
||||||
address.
|
address.
|
||||||
* Access restriction after too many authentication attempts.
|
* Access restriction after too many authentication attempts.
|
||||||
* Session management using Redis key/value store.
|
* Session management using Redis key/value store.
|
||||||
|
* User-defined access control per subdomain and resource.
|
||||||
|
|
||||||
## Deployment
|
## Deployment
|
||||||
|
|
||||||
If you don't have any LDAP and/or nginx setup yet, I advise you to follow the
|
If you don't have any LDAP and/or nginx setup yet, I advise you to follow the
|
||||||
[Getting Started](#Getting-started) section. That way, you can test it right away
|
[Getting Started](#Getting-started) section. That way, you can test it right away
|
||||||
without even configure anything.
|
without even configuring anything.
|
||||||
|
|
||||||
Otherwise here are the available steps to deploy **Authelia** on your machine given
|
Otherwise, here are the available steps to deploy **Authelia** on your machine given
|
||||||
your configuration file is **/path/to/your/config.yml**. Note that you can create your
|
your configuration file is **/path/to/your/config.yml**. Note that you can create your
|
||||||
own the configuration file from [config.template.yml] at the root of the repo.
|
own the configuration file from [config.template.yml] at the root of the repo.
|
||||||
|
|
||||||
|
@ -85,7 +86,7 @@ gave *Docker version 17.03.1-ce, build c6d412e*.
|
||||||
gave *docker-compose version 1.14.0, build c7bdf9e*.
|
gave *docker-compose version 1.14.0, build c7bdf9e*.
|
||||||
|
|
||||||
#### Available port
|
#### Available port
|
||||||
Make sure you don't have anything listening on port 8080.
|
Make sure you don't have anything listening on port 8080 (webserver) and 8085 (webmail).
|
||||||
|
|
||||||
#### Subdomain aliases
|
#### Subdomain aliases
|
||||||
|
|
||||||
|
@ -141,10 +142,16 @@ You can find an example of the configuration of the LDAP backend in [config.temp
|
||||||
### Second factor with TOTP
|
### Second factor with TOTP
|
||||||
In **Authelia**, you can register a per user TOTP (Time-Based One Time Password) secret before
|
In **Authelia**, you can register a per user TOTP (Time-Based One Time Password) secret before
|
||||||
authenticating. To do that, you need to click on the register button. It will
|
authenticating. To do that, you need to click on the register button. It will
|
||||||
|
<<<<<<< 7a2b45a66fba8ad1862f25cfa727df03d218ba83
|
||||||
send a link to the user email address defined in the LDAP.
|
send a link to the user email address defined in the LDAP.
|
||||||
Since this is an example, no email will be sent, the link is rather delivered in the file
|
Since this is an example, no email will be sent, the link is rather delivered in the file
|
||||||
**/tmp/notifications/notification.txt**. Paste the link in your browser and you'll get
|
**/tmp/notifications/notification.txt**. Paste the link in your browser and you'll get
|
||||||
your secret in QRCode and Base32 format. You can use
|
your secret in QRCode and Base32 format. You can use
|
||||||
|
=======
|
||||||
|
send a link to the user email address stored in LDAP. Since this is an example, the email is sent
|
||||||
|
to a fake email address you can access from the webmail at [http://localhost:8085](http://localhost:8085).
|
||||||
|
Click on **Continue** and you'll get your secret in QRCode and Base32 formats. You can use
|
||||||
|
>>>>>>> Add SMTP notifier as an available option in configuration
|
||||||
[Google Authenticator]
|
[Google Authenticator]
|
||||||
to store them and get the generated tokens with the app.
|
to store them and get the generated tokens with the app.
|
||||||
|
|
||||||
|
@ -155,11 +162,19 @@ to store them and get the generated tokens with the app.
|
||||||
USB security keys. U2F is one of the most secure authentication protocol and is
|
USB security keys. U2F is one of the most secure authentication protocol and is
|
||||||
already available for Google, Facebook, Github accounts and more.
|
already available for Google, Facebook, Github accounts and more.
|
||||||
|
|
||||||
|
<<<<<<< 7a2b45a66fba8ad1862f25cfa727df03d218ba83
|
||||||
Like TOTP, U2F requires you register a security key before authenticating.
|
Like TOTP, U2F requires you register a security key before authenticating.
|
||||||
To do so, click on the register link. This will send a link to the
|
To do so, click on the register link. This will send a link to the
|
||||||
user email address. Since this is an example, no email will be sent, the
|
user email address. Since this is an example, no email will be sent, the
|
||||||
link is rather delivered in the file **/tmp/notifications/notification.txt**. Paste
|
link is rather delivered in the file **/tmp/notifications/notification.txt**. Paste
|
||||||
the link in your browser and you'll be asking to touch the token of your device
|
the link in your browser and you'll be asking to touch the token of your device
|
||||||
|
=======
|
||||||
|
Like TOTP, U2F requires you register your security key before authenticating.
|
||||||
|
To do so, click on the register button. This will send a link to the
|
||||||
|
user email address. Since this is an example, the email is sent
|
||||||
|
to a fake email address you can access from the webmail at [http://localhost:8085](http://localhost:8085).
|
||||||
|
Click on **Continue** and you'll be asking to touch the token of your device
|
||||||
|
>>>>>>> Add SMTP notifier as an available option in configuration
|
||||||
to register. Upon successful registration, you can authenticate using your U2F
|
to register. Upon successful registration, you can authenticate using your U2F
|
||||||
device by simply touching the token. Easy, right?!
|
device by simply touching the token. Easy, right?!
|
||||||
|
|
||||||
|
@ -169,8 +184,8 @@ device by simply touching the token. Easy, right?!
|
||||||
With **Authelia**, you can also reset your password in no time. Click on the
|
With **Authelia**, you can also reset your password in no time. Click on the
|
||||||
**Forgot password?** link in the login page, provide the username of the user requiring
|
**Forgot password?** link in the login page, provide the username of the user requiring
|
||||||
a password reset and **Authelia** will send an email with an link to the user
|
a password reset and **Authelia** will send an email with an link to the user
|
||||||
email address. For the sake of the example, the email is delivered in the file
|
email address. For the sake of the example, the email is delivered in a fake webmail deployed
|
||||||
**/tmp/notifications/notification.txt**.
|
for you and accessible at [http://localhost:8085](http://localhost:8085).
|
||||||
Paste the link in your browser and you should be able to reset the password.
|
Paste the link in your browser and you should be able to reset the password.
|
||||||
|
|
||||||
<img src="https://raw.githubusercontent.com/clems4ever/authelia/master/images/reset_password.png" width="400">
|
<img src="https://raw.githubusercontent.com/clems4ever/authelia/master/images/reset_password.png" width="400">
|
||||||
|
|
|
@ -182,12 +182,15 @@ storage:
|
||||||
# registration or a TOTP registration.
|
# registration or a TOTP registration.
|
||||||
# Use only an available configuration: filesystem, gmail
|
# Use only an available configuration: filesystem, gmail
|
||||||
notifier:
|
notifier:
|
||||||
# For testing purpose, notifications can be sent in a file
|
|
||||||
filesystem:
|
|
||||||
filename: /var/lib/authelia/notifications/notification.txt
|
|
||||||
|
|
||||||
# Use your gmail account to send the notifications. You can use an app password.
|
# Use your gmail account to send the notifications. You can use an app password.
|
||||||
# gmail:
|
# gmail:
|
||||||
# username: user@example.com
|
# username: user@example.com
|
||||||
# password: yourpassword
|
# password: yourpassword
|
||||||
|
|
||||||
|
# Use a SMTP server for sending notifications
|
||||||
|
smtp:
|
||||||
|
username: test
|
||||||
|
password: test
|
||||||
|
secure: false
|
||||||
|
host: 'smtp'
|
||||||
|
port: 1025
|
||||||
|
|
|
@ -162,12 +162,16 @@ storage:
|
||||||
# registration or a TOTP registration.
|
# registration or a TOTP registration.
|
||||||
# Use only an available configuration: filesystem, gmail
|
# Use only an available configuration: filesystem, gmail
|
||||||
notifier:
|
notifier:
|
||||||
# For testing purpose, notifications can be sent in a file
|
|
||||||
filesystem:
|
|
||||||
filename: /var/lib/authelia/notifications/notification.txt
|
|
||||||
|
|
||||||
# Use your gmail account to send the notifications. You can use an app password.
|
# Use your gmail account to send the notifications. You can use an app password.
|
||||||
# gmail:
|
# gmail:
|
||||||
# username: user@example.com
|
# username: user@example.com
|
||||||
# password: yourpassword
|
# password: yourpassword
|
||||||
|
|
||||||
|
# Use a SMTP server for sending notifications
|
||||||
|
smtp:
|
||||||
|
username: test
|
||||||
|
password: test
|
||||||
|
secure: false
|
||||||
|
host: 'smtp'
|
||||||
|
port: 1025
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,6 @@ services:
|
||||||
restart: always
|
restart: always
|
||||||
volumes:
|
volumes:
|
||||||
- ./config.template.yml:/etc/authelia/config.yml:ro
|
- ./config.template.yml:/etc/authelia/config.yml:ro
|
||||||
- /tmp/notifications:/var/lib/authelia/notifications
|
|
||||||
depends_on:
|
depends_on:
|
||||||
- redis
|
- redis
|
||||||
networks:
|
networks:
|
||||||
|
|
|
@ -25,7 +25,7 @@ dn: cn=john,ou=users,dc=example,dc=com
|
||||||
cn: john
|
cn: john
|
||||||
objectclass: inetOrgPerson
|
objectclass: inetOrgPerson
|
||||||
objectclass: top
|
objectclass: top
|
||||||
mail: john.doe@example.com
|
mail: john.doe@authelia.com
|
||||||
sn: John Doe
|
sn: John Doe
|
||||||
userpassword: {SHA}W6ph5Mm5Pz8GgiULbPgzG37mj9g=
|
userpassword: {SHA}W6ph5Mm5Pz8GgiULbPgzG37mj9g=
|
||||||
|
|
||||||
|
@ -33,7 +33,7 @@ dn: cn=harry,ou=users,dc=example,dc=com
|
||||||
cn: harry
|
cn: harry
|
||||||
objectclass: inetOrgPerson
|
objectclass: inetOrgPerson
|
||||||
objectclass: top
|
objectclass: top
|
||||||
mail: harry.potter@example.com
|
mail: harry.potter@authelia.com
|
||||||
sn: Harry Potter
|
sn: Harry Potter
|
||||||
userpassword: {SHA}W6ph5Mm5Pz8GgiULbPgzG37mj9g=
|
userpassword: {SHA}W6ph5Mm5Pz8GgiULbPgzG37mj9g=
|
||||||
|
|
||||||
|
@ -41,7 +41,7 @@ dn: cn=bob,ou=users,dc=example,dc=com
|
||||||
cn: bob
|
cn: bob
|
||||||
objectclass: inetOrgPerson
|
objectclass: inetOrgPerson
|
||||||
objectclass: top
|
objectclass: top
|
||||||
mail: bob.dylan@example.com
|
mail: bob.dylan@authelia.com
|
||||||
sn: Bob Dylan
|
sn: Bob Dylan
|
||||||
userpassword: {SHA}W6ph5Mm5Pz8GgiULbPgzG37mj9g=
|
userpassword: {SHA}W6ph5Mm5Pz8GgiULbPgzG37mj9g=
|
||||||
|
|
||||||
|
@ -49,7 +49,7 @@ dn: cn=james,ou=users,dc=example,dc=com
|
||||||
cn: james
|
cn: james
|
||||||
objectclass: inetOrgPerson
|
objectclass: inetOrgPerson
|
||||||
objectclass: top
|
objectclass: top
|
||||||
mail: james.dean@example.com
|
mail: james.dean@authelia.com
|
||||||
sn: James Dean
|
sn: James Dean
|
||||||
userpassword: {SHA}W6ph5Mm5Pz8GgiULbPgzG37mj9g=
|
userpassword: {SHA}W6ph5Mm5Pz8GgiULbPgzG37mj9g=
|
||||||
|
|
||||||
|
@ -57,6 +57,6 @@ dn: cn=blackhat,ou=users,dc=example,dc=com
|
||||||
cn: blackhat
|
cn: blackhat
|
||||||
objectclass: inetOrgPerson
|
objectclass: inetOrgPerson
|
||||||
objectclass: top
|
objectclass: top
|
||||||
mail: billy.blackhat@example.com
|
mail: billy.blackhat@authelia.com
|
||||||
sn: Billy BlackHat
|
sn: Billy BlackHat
|
||||||
userpassword: {SHA}W6ph5Mm5Pz8GgiULbPgzG37mj9g=
|
userpassword: {SHA}W6ph5Mm5Pz8GgiULbPgzG37mj9g=
|
||||||
|
|
|
@ -12,6 +12,7 @@ services:
|
||||||
- SLAPD_FORCE_RECONFIGURE=true
|
- SLAPD_FORCE_RECONFIGURE=true
|
||||||
volumes:
|
volumes:
|
||||||
- ./example/ldap/base.ldif:/etc/ldap.dist/prepopulate/base.ldif
|
- ./example/ldap/base.ldif:/etc/ldap.dist/prepopulate/base.ldif
|
||||||
|
- ./example/ldap/private.ldif:/etc/ldap.dist/prepopulate/private.ldif
|
||||||
- ./example/ldap/access.rules:/etc/ldap.dist/prepopulate/access.rules
|
- ./example/ldap/access.rules:/etc/ldap.dist/prepopulate/access.rules
|
||||||
networks:
|
networks:
|
||||||
- example-network
|
- example-network
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
version: '2'
|
||||||
|
services:
|
||||||
|
smtp:
|
||||||
|
image: schickling/mailcatcher
|
||||||
|
ports:
|
||||||
|
- "8085:1080"
|
||||||
|
networks:
|
||||||
|
- example-network
|
|
@ -66,6 +66,7 @@
|
||||||
"@types/randomstring": "^1.1.5",
|
"@types/randomstring": "^1.1.5",
|
||||||
"@types/redis": "^2.6.0",
|
"@types/redis": "^2.6.0",
|
||||||
"@types/request": "0.0.46",
|
"@types/request": "0.0.46",
|
||||||
|
"@types/request-promise": "^4.1.37",
|
||||||
"@types/selenium-webdriver": "^3.0.4",
|
"@types/selenium-webdriver": "^3.0.4",
|
||||||
"@types/sinon": "^2.2.1",
|
"@types/sinon": "^2.2.1",
|
||||||
"@types/speakeasy": "^2.0.1",
|
"@types/speakeasy": "^2.0.1",
|
||||||
|
@ -94,6 +95,7 @@
|
||||||
"proxyquire": "^1.8.0",
|
"proxyquire": "^1.8.0",
|
||||||
"query-string": "^4.3.4",
|
"query-string": "^4.3.4",
|
||||||
"request": "^2.81.0",
|
"request": "^2.81.0",
|
||||||
|
"request-promise": "^4.2.2",
|
||||||
"selenium-webdriver": "^3.5.0",
|
"selenium-webdriver": "^3.5.0",
|
||||||
"should": "^11.1.1",
|
"should": "^11.1.1",
|
||||||
"sinon": "^2.3.8",
|
"sinon": "^2.3.8",
|
||||||
|
|
|
@ -9,5 +9,6 @@ docker-compose \
|
||||||
-f example/mongo/docker-compose.yml \
|
-f example/mongo/docker-compose.yml \
|
||||||
-f example/redis/docker-compose.yml \
|
-f example/redis/docker-compose.yml \
|
||||||
-f example/nginx/docker-compose.yml \
|
-f example/nginx/docker-compose.yml \
|
||||||
|
-f example/smtp/docker-compose.yml \
|
||||||
-f example/ldap/docker-compose.admin.yml \
|
-f example/ldap/docker-compose.admin.yml \
|
||||||
-f example/ldap/docker-compose.yml $*
|
-f example/ldap/docker-compose.yml $*
|
||||||
|
|
|
@ -8,4 +8,5 @@ docker-compose \
|
||||||
-f example/mongo/docker-compose.yml \
|
-f example/mongo/docker-compose.yml \
|
||||||
-f example/redis/docker-compose.yml \
|
-f example/redis/docker-compose.yml \
|
||||||
-f example/nginx/docker-compose.yml \
|
-f example/nginx/docker-compose.yml \
|
||||||
|
-f example/smtp/docker-compose.yml \
|
||||||
-f example/ldap/docker-compose.yml $*
|
-f example/ldap/docker-compose.yml $*
|
||||||
|
|
|
@ -3,4 +3,4 @@
|
||||||
DC_SCRIPT=./scripts/example-commit/dc-example.sh
|
DC_SCRIPT=./scripts/example-commit/dc-example.sh
|
||||||
|
|
||||||
$DC_SCRIPT build
|
$DC_SCRIPT build
|
||||||
$DC_SCRIPT up -d mongo redis openldap authelia nginx
|
$DC_SCRIPT up -d mongo redis openldap authelia nginx smtp
|
||||||
|
|
|
@ -8,4 +8,5 @@ docker-compose \
|
||||||
-f example/mongo/docker-compose.yml \
|
-f example/mongo/docker-compose.yml \
|
||||||
-f example/redis/docker-compose.yml \
|
-f example/redis/docker-compose.yml \
|
||||||
-f example/nginx/docker-compose.yml \
|
-f example/nginx/docker-compose.yml \
|
||||||
|
-f example/smtp/docker-compose.yml \
|
||||||
-f example/ldap/docker-compose.yml $*
|
-f example/ldap/docker-compose.yml $*
|
||||||
|
|
|
@ -3,4 +3,4 @@
|
||||||
DC_SCRIPT=./scripts/example-dockerhub/dc-example.sh
|
DC_SCRIPT=./scripts/example-dockerhub/dc-example.sh
|
||||||
|
|
||||||
#$DC_SCRIPT build
|
#$DC_SCRIPT build
|
||||||
$DC_SCRIPT up -d mongo redis openldap authelia nginx
|
$DC_SCRIPT up -d mongo redis openldap authelia nginx smtp
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
DC_SCRIPT=./scripts/example-commit/dc-example.sh
|
DC_SCRIPT=./scripts/example-commit/dc-example.sh
|
||||||
EXPECTED_SERVICES_COUNT=5
|
EXPECTED_SERVICES_COUNT=6
|
||||||
|
|
||||||
start_services() {
|
start_services() {
|
||||||
$DC_SCRIPT up -d mongo redis openldap authelia nginx
|
$DC_SCRIPT up -d mongo redis openldap authelia nginx smtp
|
||||||
sleep 3
|
sleep 3
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,13 +41,13 @@ run_other_tests() {
|
||||||
npm install --only=dev
|
npm install --only=dev
|
||||||
./node_modules/.bin/grunt build-dist
|
./node_modules/.bin/grunt build-dist
|
||||||
./scripts/example-commit/deploy-example.sh
|
./scripts/example-commit/deploy-example.sh
|
||||||
expect_services_count 5
|
expect_services_count $EXPECTED_SERVICES_COUNT
|
||||||
}
|
}
|
||||||
|
|
||||||
run_other_tests_docker() {
|
run_other_tests_docker() {
|
||||||
echo "Test dev docker deployment (commands in README)"
|
echo "Test dev docker deployment (commands in README)"
|
||||||
./scripts/example-dockerhub/deploy-example.sh
|
./scripts/example-dockerhub/deploy-example.sh
|
||||||
expect_services_count 5
|
expect_services_count $EXPECTED_SERVICES_COUNT
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -71,12 +71,21 @@ export interface GmailNotifierConfiguration {
|
||||||
password: string;
|
password: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface SmtpNotifierConfiguration {
|
||||||
|
username: string;
|
||||||
|
password: string;
|
||||||
|
host: string;
|
||||||
|
port: number;
|
||||||
|
secure: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
export interface FileSystemNotifierConfiguration {
|
export interface FileSystemNotifierConfiguration {
|
||||||
filename: string;
|
filename: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface NotifierConfiguration {
|
export interface NotifierConfiguration {
|
||||||
gmail?: GmailNotifierConfiguration;
|
gmail?: GmailNotifierConfiguration;
|
||||||
|
smtp?: SmtpNotifierConfiguration;
|
||||||
filesystem?: FileSystemNotifierConfiguration;
|
filesystem?: FileSystemNotifierConfiguration;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
|
||||||
|
import { INotifier } from "../notifiers/INotifier";
|
||||||
|
import { Identity } from "../../../types/Identity";
|
||||||
|
|
||||||
|
import Fs = require("fs");
|
||||||
|
import Path = require("path");
|
||||||
|
import Ejs = require("ejs");
|
||||||
|
import BluebirdPromise = require("bluebird");
|
||||||
|
|
||||||
|
const email_template = Fs.readFileSync(Path.join(__dirname, "../../resources/email-template.ejs"), "UTF-8");
|
||||||
|
|
||||||
|
export abstract class AbstractEmailNotifier implements INotifier {
|
||||||
|
|
||||||
|
notify(identity: Identity, subject: string, link: string): BluebirdPromise<void> {
|
||||||
|
const d = {
|
||||||
|
url: link,
|
||||||
|
button_title: "Continue",
|
||||||
|
title: subject
|
||||||
|
};
|
||||||
|
return this.sendEmail(identity.email, subject, Ejs.render(email_template, d));
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract sendEmail(email: string, subject: string, content: string): BluebirdPromise<void>;
|
||||||
|
}
|
|
@ -1,21 +1,16 @@
|
||||||
|
|
||||||
import * as BluebirdPromise from "bluebird";
|
import * as BluebirdPromise from "bluebird";
|
||||||
import * as fs from "fs";
|
|
||||||
import * as ejs from "ejs";
|
|
||||||
import nodemailer = require("nodemailer");
|
import nodemailer = require("nodemailer");
|
||||||
|
|
||||||
import { Nodemailer } from "../../../types/Dependencies";
|
import { Nodemailer } from "../../../types/Dependencies";
|
||||||
import { Identity } from "../../../types/Identity";
|
import { AbstractEmailNotifier } from "../notifiers/AbstractEmailNotifier";
|
||||||
import { INotifier } from "../notifiers/INotifier";
|
|
||||||
import { GmailNotifierConfiguration } from "../configuration/Configuration";
|
import { GmailNotifierConfiguration } from "../configuration/Configuration";
|
||||||
import path = require("path");
|
|
||||||
|
|
||||||
const email_template = fs.readFileSync(path.join(__dirname, "../../resources/email-template.ejs"), "UTF-8");
|
export class GMailNotifier extends AbstractEmailNotifier {
|
||||||
|
|
||||||
export class GMailNotifier implements INotifier {
|
|
||||||
private transporter: any;
|
private transporter: any;
|
||||||
|
|
||||||
constructor(options: GmailNotifierConfiguration, nodemailer: Nodemailer) {
|
constructor(options: GmailNotifierConfiguration, nodemailer: Nodemailer) {
|
||||||
|
super();
|
||||||
const transporter = nodemailer.createTransport({
|
const transporter = nodemailer.createTransport({
|
||||||
service: "gmail",
|
service: "gmail",
|
||||||
auth: {
|
auth: {
|
||||||
|
@ -26,18 +21,12 @@ export class GMailNotifier implements INotifier {
|
||||||
this.transporter = BluebirdPromise.promisifyAll(transporter);
|
this.transporter = BluebirdPromise.promisifyAll(transporter);
|
||||||
}
|
}
|
||||||
|
|
||||||
notify(identity: Identity, subject: string, link: string): BluebirdPromise<void> {
|
sendEmail(email: string, subject: string, content: string) {
|
||||||
const d = {
|
|
||||||
url: link,
|
|
||||||
button_title: "Continue",
|
|
||||||
title: subject
|
|
||||||
};
|
|
||||||
|
|
||||||
const mailOptions = {
|
const mailOptions = {
|
||||||
from: "authelia@authelia.com",
|
from: "authelia@authelia.com",
|
||||||
to: identity.email,
|
to: email,
|
||||||
subject: subject,
|
subject: subject,
|
||||||
html: ejs.render(email_template, d)
|
html: content
|
||||||
};
|
};
|
||||||
return this.transporter.sendMailAsync(mailOptions);
|
return this.transporter.sendMailAsync(mailOptions);
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ import { Nodemailer } from "../../../types/Dependencies";
|
||||||
import { INotifier } from "./INotifier";
|
import { INotifier } from "./INotifier";
|
||||||
|
|
||||||
import { GMailNotifier } from "./GMailNotifier";
|
import { GMailNotifier } from "./GMailNotifier";
|
||||||
|
import { SmtpNotifier } from "./SmtpNotifier";
|
||||||
import { FileSystemNotifier } from "./FileSystemNotifier";
|
import { FileSystemNotifier } from "./FileSystemNotifier";
|
||||||
|
|
||||||
export class NotifierFactory {
|
export class NotifierFactory {
|
||||||
|
@ -14,6 +15,12 @@ export class NotifierFactory {
|
||||||
else if ("filesystem" in options) {
|
else if ("filesystem" in options) {
|
||||||
return new FileSystemNotifier(options.filesystem);
|
return new FileSystemNotifier(options.filesystem);
|
||||||
}
|
}
|
||||||
|
else if ("smtp" in options) {
|
||||||
|
return new SmtpNotifier(options.smtp, nodemailer);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw new Error("No available notifier option detected.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,53 @@
|
||||||
|
|
||||||
|
|
||||||
|
import * as BluebirdPromise from "bluebird";
|
||||||
|
import Nodemailer = require("nodemailer");
|
||||||
|
|
||||||
|
import { AbstractEmailNotifier } from "../notifiers/AbstractEmailNotifier";
|
||||||
|
import { SmtpNotifierConfiguration } from "../configuration/Configuration";
|
||||||
|
|
||||||
|
export class SmtpNotifier extends AbstractEmailNotifier {
|
||||||
|
private transporter: any;
|
||||||
|
|
||||||
|
constructor(options: SmtpNotifierConfiguration, nodemailer: typeof Nodemailer) {
|
||||||
|
super();
|
||||||
|
const smtpOptions = {
|
||||||
|
host: options.host,
|
||||||
|
port: options.port,
|
||||||
|
secure: options.secure, // upgrade later with STARTTLS
|
||||||
|
auth: {
|
||||||
|
user: options.username,
|
||||||
|
pass: options.password
|
||||||
|
}
|
||||||
|
};
|
||||||
|
console.log(smtpOptions);
|
||||||
|
const transporter = nodemailer.createTransport(smtpOptions);
|
||||||
|
this.transporter = BluebirdPromise.promisifyAll(transporter);
|
||||||
|
|
||||||
|
// verify connection configuration
|
||||||
|
console.log("Checking SMTP server connection.");
|
||||||
|
transporter.verify(function (error, success) {
|
||||||
|
if (error) {
|
||||||
|
throw new Error("Unable to connect to SMTP server. \
|
||||||
|
Please check the service is running and your credentials are correct.");
|
||||||
|
} else {
|
||||||
|
console.log("SMTP Server is ready to take our messages");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
sendEmail(email: string, subject: string, content: string) {
|
||||||
|
const mailOptions = {
|
||||||
|
from: "authelia@authelia.com",
|
||||||
|
to: email,
|
||||||
|
subject: subject,
|
||||||
|
html: content
|
||||||
|
};
|
||||||
|
return this.transporter.sendMail(mailOptions, (error: Error, data: string) => {
|
||||||
|
if (error) {
|
||||||
|
return console.log(error);
|
||||||
|
}
|
||||||
|
console.log("Message sent: %s", JSON.stringify(data));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -9,12 +9,10 @@ Cucumber.defineSupportCode(function ({ Given, When, Then }) {
|
||||||
});
|
});
|
||||||
|
|
||||||
When("I click on the link of the email", function () {
|
When("I click on the link of the email", function () {
|
||||||
const notif = Fs.readFileSync("/tmp/notifications/notification.txt").toString();
|
|
||||||
const regexp = new RegExp(/Link: (.+)/);
|
|
||||||
const match = regexp.exec(notif);
|
|
||||||
const link = match[1];
|
|
||||||
const that = this;
|
const that = this;
|
||||||
|
return this.retrieveLatestMail()
|
||||||
return this.driver.get(link);
|
.then(function (link: string) {
|
||||||
|
return that.driver.get(link);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
|
@ -4,6 +4,8 @@ import Cucumber = require("cucumber");
|
||||||
import Fs = require("fs");
|
import Fs = require("fs");
|
||||||
import Speakeasy = require("speakeasy");
|
import Speakeasy = require("speakeasy");
|
||||||
import Assert = require("assert");
|
import Assert = require("assert");
|
||||||
|
import Request = require("request-promise");
|
||||||
|
import BluebirdPromise = require("bluebird");
|
||||||
|
|
||||||
function CustomWorld() {
|
function CustomWorld() {
|
||||||
const that = this;
|
const that = this;
|
||||||
|
@ -49,7 +51,7 @@ function CustomWorld() {
|
||||||
.click();
|
.click();
|
||||||
})
|
})
|
||||||
.then(function () {
|
.then(function () {
|
||||||
return that.driver.sleep(500);
|
return that.driver.sleep(1000);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -69,18 +71,37 @@ function CustomWorld() {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
this.retrieveLatestMail = function () {
|
||||||
|
return Request({
|
||||||
|
method: "GET",
|
||||||
|
uri: "http://localhost:8085/messages",
|
||||||
|
json: true
|
||||||
|
})
|
||||||
|
.then(function (data: any) {
|
||||||
|
const messageId = data[data.length - 1].id;
|
||||||
|
return Request({
|
||||||
|
method: "GET",
|
||||||
|
uri: `http://localhost:8085/messages/${messageId}.html`
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.then(function (data: any) {
|
||||||
|
const regexp = new RegExp(/<a href="(.+)" class="button">Continue<\/a>/);
|
||||||
|
const match = regexp.exec(data);
|
||||||
|
const link = match[1];
|
||||||
|
return BluebirdPromise.resolve(link);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
this.registerTotpSecret = function (totpSecretHandle: string) {
|
this.registerTotpSecret = function (totpSecretHandle: string) {
|
||||||
return that.driver.wait(seleniumWebdriver.until.elementLocated(seleniumWebdriver.By.className("register-totp")), 4000)
|
return that.driver.wait(seleniumWebdriver.until.elementLocated(seleniumWebdriver.By.className("register-totp")), 4000)
|
||||||
.then(function () {
|
.then(function () {
|
||||||
return that.driver.findElement(seleniumWebdriver.By.className("register-totp")).click();
|
return that.driver.findElement(seleniumWebdriver.By.className("register-totp")).click();
|
||||||
})
|
})
|
||||||
.then(function () {
|
.then(function () {
|
||||||
const notif = Fs.readFileSync("/tmp/notifications/notification.txt").toString();
|
return that.retrieveLatestMail();
|
||||||
const regexp = new RegExp(/Link: (.+)/);
|
})
|
||||||
const match = regexp.exec(notif);
|
.then(function (url: string) {
|
||||||
const link = match[1];
|
return that.driver.get(url);
|
||||||
console.log("Link: " + link);
|
|
||||||
return that.driver.get(link);
|
|
||||||
})
|
})
|
||||||
.then(function () {
|
.then(function () {
|
||||||
return that.driver.wait(seleniumWebdriver.until.elementLocated(seleniumWebdriver.By.id("secret")), 5000);
|
return that.driver.wait(seleniumWebdriver.until.elementLocated(seleniumWebdriver.By.id("secret")), 5000);
|
||||||
|
|
Loading…
Reference in New Issue