Less restrictive email handler - replace gmail with generic

pull/181/head
Dylan Smith 2017-10-25 19:28:56 +11:00
parent 5570ac3d84
commit c62b85e37d
19 changed files with 82 additions and 64 deletions

View File

@ -203,11 +203,13 @@ notifier:
# filesystem:
# filename: /tmp/authelia/notification.txt
# Use your gmail account to send the notifications. You can use an app password.
# gmail:
# Use your email account to send the notifications. You can use an app password.
# List of valid services can be found here: https://nodemailer.com/smtp/well-known/
# email:
# username: user@example.com
# password: yourpassword
# sender: admin@example.com
# service: gmail
# Use a SMTP server for sending notifications
smtp:

View File

@ -178,11 +178,13 @@ storage:
# registration or a TOTP registration.
# Use only an available configuration: filesystem, gmail
notifier:
# Use your gmail account to send the notifications. You can use an app password.
# gmail:
# Use your email account to send the notifications. You can use an app password.
# List of valid services can be found here: https://nodemailer.com/smtp/well-known/
# email:
# username: user@example.com
# password: yourpassword
# sender: admin@example.com
# service: gmail
# Use a SMTP server for sending notifications
smtp:

View File

@ -71,15 +71,15 @@ export default class Server {
displayableUserConfiguration.ldap.password = STARS;
displayableUserConfiguration.session.secret = STARS;
if (displayableUserConfiguration.notifier && displayableUserConfiguration.notifier.gmail)
displayableUserConfiguration.notifier.gmail.password = STARS;
if (displayableUserConfiguration.notifier && displayableUserConfiguration.notifier.email)
displayableUserConfiguration.notifier.email.password = STARS;
if (displayableUserConfiguration.notifier && displayableUserConfiguration.notifier.smtp)
displayableUserConfiguration.notifier.smtp.password = STARS;
displayableAppConfiguration.ldap.password = STARS;
displayableAppConfiguration.session.secret = STARS;
if (displayableAppConfiguration.notifier && displayableAppConfiguration.notifier.gmail)
displayableAppConfiguration.notifier.gmail.password = STARS;
if (displayableAppConfiguration.notifier && displayableAppConfiguration.notifier.email)
displayableAppConfiguration.notifier.email.password = STARS;
if (displayableAppConfiguration.notifier && displayableAppConfiguration.notifier.smtp)
displayableAppConfiguration.notifier.smtp.password = STARS;

View File

@ -66,10 +66,11 @@ interface SessionCookieConfiguration {
redis?: SessionRedisOptions;
}
export interface GmailNotifierConfiguration {
export interface EmailNotifierConfiguration {
username: string;
password: string;
sender: string;
service: string;
}
export interface SmtpNotifierConfiguration {
@ -86,7 +87,7 @@ export interface FileSystemNotifierConfiguration {
}
export interface NotifierConfiguration {
gmail?: GmailNotifierConfiguration;
email?: EmailNotifierConfiguration;
smtp?: SmtpNotifierConfiguration;
filesystem?: FileSystemNotifierConfiguration;
}

View File

@ -54,19 +54,19 @@ function validateStorage(storage: any) {
}
function validateNotifier(notifier: NotifierConfiguration) {
const ERROR = "Notifier must be either 'filesystem', 'gmail' or 'smtp'";
const ERROR = "Notifier must be either 'filesystem', 'email' or 'smtp'";
if (!notifier)
return [];
const errors = validateUnknownKeys("notifier", notifier, ["filesystem", "gmail", "smtp"]);
const errors = validateUnknownKeys("notifier", notifier, ["filesystem", "email", "smtp"]);
if (errors.length > 0)
return errors;
if (notifier && notifier.filesystem && notifier.gmail && notifier.smtp)
if (notifier && notifier.filesystem && notifier.email && notifier.smtp)
return [ERROR];
if (notifier && !notifier.filesystem && !notifier.gmail && !notifier.smtp)
if (notifier && !notifier.filesystem && !notifier.email && !notifier.smtp)
return [ERROR];
return [];

View File

@ -2,14 +2,14 @@
import * as BluebirdPromise from "bluebird";
import { AbstractEmailNotifier } from "../notifiers/AbstractEmailNotifier";
import { GmailNotifierConfiguration } from "../configuration/Configuration";
import { EmailNotifierConfiguration } from "../configuration/Configuration";
import { IMailSender } from "./IMailSender";
export class GMailNotifier extends AbstractEmailNotifier {
export class EMailNotifier extends AbstractEmailNotifier {
private mailSender: IMailSender;
private sender: string;
constructor(options: GmailNotifierConfiguration, mailSender: IMailSender) {
constructor(options: EmailNotifierConfiguration, mailSender: IMailSender) {
super();
this.mailSender = mailSender;
this.sender = options.sender;

View File

@ -1,7 +1,7 @@
import { IMailSender } from "./IMailSender";
import { SmtpNotifierConfiguration, GmailNotifierConfiguration } from "../configuration/Configuration";
import { SmtpNotifierConfiguration, EmailNotifierConfiguration } from "../configuration/Configuration";
export interface IMailSenderBuilder {
buildGmail(options: GmailNotifierConfiguration): IMailSender;
buildEmail(options: EmailNotifierConfiguration): IMailSender;
buildSmtp(options: SmtpNotifierConfiguration): IMailSender;
}

View File

@ -3,7 +3,7 @@ import { IMailSenderBuilder } from "./IMailSenderBuilder";
import { MailSender } from "./MailSender";
import Nodemailer = require("nodemailer");
import NodemailerSmtpTransport = require("nodemailer-smtp-transport");
import { SmtpNotifierConfiguration, GmailNotifierConfiguration } from "../configuration/Configuration";
import { SmtpNotifierConfiguration, EmailNotifierConfiguration } from "../configuration/Configuration";
export class MailSenderBuilder implements IMailSenderBuilder {
private nodemailer: typeof Nodemailer;
@ -12,15 +12,15 @@ export class MailSenderBuilder implements IMailSenderBuilder {
this.nodemailer = nodemailer;
}
buildGmail(options: GmailNotifierConfiguration): IMailSender {
const gmailOptions = {
service: "gmail",
buildEmail(options: EmailNotifierConfiguration): IMailSender {
const emailOptions = {
service: options.service,
auth: {
user: options.username,
pass: options.password
}
};
return new MailSender(gmailOptions, this.nodemailer);
return new MailSender(emailOptions, this.nodemailer);
}
buildSmtp(options: SmtpNotifierConfiguration): IMailSender {

View File

@ -4,16 +4,16 @@ import Nodemailer = require("nodemailer");
import { INotifier } from "./INotifier";
import { FileSystemNotifier } from "./FileSystemNotifier";
import { GMailNotifier } from "./GMailNotifier";
import { EMailNotifier } from "./EMailNotifier";
import { SmtpNotifier } from "./SmtpNotifier";
import { IMailSender } from "./IMailSender";
import { IMailSenderBuilder } from "./IMailSenderBuilder";
export class NotifierFactory {
static build(options: NotifierConfiguration, mailSenderBuilder: IMailSenderBuilder): INotifier {
if ("gmail" in options) {
const mailSender = mailSenderBuilder.buildGmail(options.gmail);
return new GMailNotifier(options.gmail, mailSender);
if ("email" in options) {
const mailSender = mailSenderBuilder.buildEmail(options.email);
return new EMailNotifier(options.email, mailSender);
}
else if ("smtp" in options) {
const mailSender = mailSenderBuilder.buildSmtp(options.smtp);

View File

@ -53,10 +53,11 @@ describe("test server configuration", function () {
base_dn: "dc=example,dc=com"
},
notifier: {
gmail: {
email: {
username: "user@example.com",
password: "password",
sender: "test@authelia.com"
sender: "test@authelia.com",
service: "gmail"
}
},
regulation: {

View File

@ -34,10 +34,11 @@ describe("test config parser", function () {
},
logs_level: "debug",
notifier: {
gmail: {
email: {
username: "user",
password: "password",
sender: "admin@example.com"
sender: "admin@example.com",
service: "gmail"
}
}
};
@ -83,18 +84,20 @@ describe("test config parser", function () {
it("should get the notifier config", function () {
const userConfig = buildYamlConfig();
userConfig.notifier = {
gmail: {
email: {
username: "user",
password: "pass",
sender: "admin@example.com"
sender: "admin@example.com",
service: "gmail"
}
};
const config = ConfigurationParser.parse(userConfig);
Assert.deepEqual(config.notifier, {
gmail: {
email: {
username: "user",
password: "pass",
sender: "admin@example.com"
sender: "admin@example.com",
service: "gmail"
}
});
});

View File

@ -31,10 +31,11 @@ describe("test ldap configuration adaptation", function () {
},
logs_level: "debug",
notifier: {
gmail: {
email: {
username: "user",
password: "password",
sender: "admin@example.com"
sender: "admin@example.com",
service: "email"
}
}
};

View File

@ -28,7 +28,7 @@ describe("test validator", function () {
"data.regulation should have required property 'max_retries'",
"data.session should have required property 'secret'",
"Storage must be either 'local' or 'mongo'",
"Notifier must be either 'filesystem', 'gmail' or 'smtp'"
"Notifier must be either 'filesystem', 'email' or 'smtp'"
]);
Assert.deepStrictEqual(Validator.isValid({
@ -67,10 +67,11 @@ describe("test validator", function () {
user: "user"
},
notifier: {
gmail: {
email: {
username: "user@gmail.com",
password: "pass",
sender: "admin@example.com"
sender: "admin@example.com",
service: "gmail"
}
},
regulation: {

View File

@ -3,19 +3,19 @@ import BluebirdPromise = require("bluebird");
import Nodemailer = require("nodemailer");
import Sinon = require("sinon");
import { IMailSender } from "../../../src/lib/notifiers/IMailSender";
import { SmtpNotifierConfiguration, GmailNotifierConfiguration } from "../../../src/lib/configuration/Configuration";
import { SmtpNotifierConfiguration, EmailNotifierConfiguration } from "../../../src/lib/configuration/Configuration";
export class MailSenderBuilderStub implements IMailSenderBuilder {
buildGmailStub: Sinon.SinonStub;
buildEmailStub: Sinon.SinonStub;
buildSmtpStub: Sinon.SinonStub;
constructor() {
this.buildGmailStub = Sinon.stub();
this.buildEmailStub = Sinon.stub();
this.buildSmtpStub = Sinon.stub();
}
buildGmail(options: GmailNotifierConfiguration): IMailSender {
return this.buildGmailStub(options);
buildEmail(options: EmailNotifierConfiguration): IMailSender {
return this.buildEmailStub(options);
}
buildSmtp(options: SmtpNotifierConfiguration): IMailSender {

View File

@ -3,20 +3,21 @@ import * as Assert from "assert";
import BluebirdPromise = require("bluebird");
import { MailSenderStub } from "../mocks/notifiers/MailSenderStub";
import GMailNotifier = require("../../src/lib/notifiers/GMailNotifier");
import EMailNotifier = require("../../src/lib/notifiers/EMailNotifier");
describe("test gmail notifier", function () {
describe("test email notifier", function () {
it("should send an email to given user", function () {
const mailSender = new MailSenderStub();
const options = {
username: "user_gmail",
password: "pass_gmail",
sender: "admin@example.com"
sender: "admin@example.com",
service: "gmail"
};
mailSender.sendStub.returns(BluebirdPromise.resolve());
const sender = new GMailNotifier.GMailNotifier(options, mailSender);
const sender = new EMailNotifier.EMailNotifier(options, mailSender);
const subject = "subject";
const url = "http://test.com";
@ -33,11 +34,12 @@ describe("test gmail notifier", function () {
const options = {
username: "user_gmail",
password: "pass_gmail",
sender: "admin@example.com"
sender: "admin@example.com",
service: "gmail"
};
mailSender.sendStub.returns(BluebirdPromise.reject(new Error("Failed to send mail")));
const sender = new GMailNotifier.GMailNotifier(options, mailSender);
const sender = new EMailNotifier.EMailNotifier(options, mailSender);
const subject = "subject";
const url = "http://test.com";

View File

@ -14,15 +14,17 @@ describe("test MailSenderBuilder", function() {
createTransportStub.restore();
});
it("should create a gmail mail sender", function() {
it("should create a email mail sender", function() {
const mailSenderBuilder = new MailSenderBuilder(Nodemailer);
mailSenderBuilder.buildGmail({
mailSenderBuilder.buildEmail({
username: "user_gmail",
password: "pass_gmail",
sender: "admin@example.com"
sender: "admin@example.com",
service: "gmail"
});
Assert.equal(createTransportStub.getCall(0).args[0].auth.user, "user_gmail");
Assert.equal(createTransportStub.getCall(0).args[0].auth.pass, "pass_gmail");
Assert.equal(createTransportStub.getCall(0).args[0].service, "gmail");
});
describe("build smtp mail sender", function() {

View File

@ -4,23 +4,24 @@ import * as BluebirdPromise from "bluebird";
import * as assert from "assert";
import { NotifierFactory } from "../../src/lib/notifiers/NotifierFactory";
import { GMailNotifier } from "../../src/lib/notifiers/GMailNotifier";
import { EMailNotifier } from "../../src/lib/notifiers/EMailNotifier";
import { SmtpNotifier } from "../../src/lib/notifiers/SmtpNotifier";
import { MailSenderBuilderStub } from "../mocks/notifiers/MailSenderBuilderStub";
describe("test notifier factory", function () {
let mailSenderBuilderStub: MailSenderBuilderStub;
it("should build a Gmail Notifier", function () {
it("should build a Email Notifier", function () {
const options = {
gmail: {
email: {
username: "abc",
password: "password",
sender: "admin@example.com"
sender: "admin@example.com",
service: "gmail"
}
};
mailSenderBuilderStub = new MailSenderBuilderStub();
assert(NotifierFactory.build(options, mailSenderBuilderStub) instanceof GMailNotifier);
assert(NotifierFactory.build(options, mailSenderBuilderStub) instanceof EMailNotifier);
});
it("should build a SMTP Notifier", function () {

View File

@ -52,10 +52,11 @@ describe("Private pages of the server must not be accessible without session", f
}
},
notifier: {
gmail: {
email: {
username: "user@example.com",
password: "password",
sender: "admin@example.com"
sender: "admin@example.com",
service: "gmail"
}
}
};

View File

@ -52,10 +52,11 @@ describe("Public pages of the server must be accessible without session", functi
find_time: 5 * 60
},
notifier: {
gmail: {
email: {
username: "user@example.com",
password: "password",
sender: "admin@example.com"
sender: "admin@example.com",
service: "gmail"
}
}
};