Refactor SendMailSSL, rename 'stoping' to 'stopping',

- Refactor SendMailSSL into smaller portions and with proper exception handling (do not catch the Exception superclass and do not nest try-catch blocks; always pass on the exception type and message)
- Clean prose in config.yml
This commit is contained in:
ljacqu 2015-12-21 22:14:40 +01:00
parent 874d7cd59f
commit 02c366637e
4 changed files with 164 additions and 139 deletions

View File

@ -9,15 +9,16 @@ public class AuthMeServerStop extends Thread {
private AuthMe plugin; private AuthMe plugin;
public AuthMeServerStop(AuthMe plugin) public AuthMeServerStop(AuthMe plugin) {
{
this.plugin = plugin; this.plugin = plugin;
} }
public void run() { public void run() {
// TODO: add a MessageKey // TODO: add a MessageKey
if (Settings.kickPlayersBeforeStoping) if (Settings.kickPlayersBeforeStopping) {
for (Player p : plugin.getServer().getOnlinePlayers()) for (Player p : plugin.getServer().getOnlinePlayers()) {
p.kickPlayer("Server is restarting"); p.kickPlayer("Server is restarting");
} }
} }
}
}

View File

@ -6,6 +6,7 @@ import fr.xephi.authme.ImageGenerator;
import fr.xephi.authme.cache.auth.PlayerAuth; import fr.xephi.authme.cache.auth.PlayerAuth;
import fr.xephi.authme.settings.Settings; import fr.xephi.authme.settings.Settings;
import fr.xephi.authme.util.StringUtils;
import org.apache.commons.mail.DefaultAuthenticator; import org.apache.commons.mail.DefaultAuthenticator;
import org.apache.commons.mail.EmailException; import org.apache.commons.mail.EmailException;
import org.apache.commons.mail.HtmlEmail; import org.apache.commons.mail.HtmlEmail;
@ -15,75 +16,139 @@ import javax.activation.DataSource;
import javax.activation.FileDataSource; import javax.activation.FileDataSource;
import javax.imageio.ImageIO; import javax.imageio.ImageIO;
import java.io.File; import java.io.File;
import java.io.IOException;
import java.security.Security; import java.security.Security;
import java.util.Properties;
/** /**
* @author Xephi59 * @author Xephi59
* @version $Revision: 1.0 $
*/ */
public class SendMailSSL { public class SendMailSSL {
public final AuthMe plugin; private final AuthMe plugin;
/**
* Constructor for SendMailSSL.
*
* @param plugin AuthMe
*/
public SendMailSSL(AuthMe plugin) { public SendMailSSL(AuthMe plugin) {
this.plugin = plugin; this.plugin = plugin;
} }
/**
* Method main.
*
* @param auth PlayerAuth
* @param newPass String
*/
public void main(final PlayerAuth auth, final String newPass) { public void main(final PlayerAuth auth, final String newPass) {
String senderName; final int port = Settings.getMailPort;
final String mailText = replaceMailTags(Settings.getMailText, plugin, auth, newPass);
Bukkit.getScheduler().runTaskAsynchronously(plugin, new Runnable() {
@Override
public void run() {
Thread.currentThread().setContextClassLoader(this.getClass().getClassLoader());
HtmlEmail email;
try {
email = initializeMail(auth);
setPropertiesForPort(port, email);
} catch (EmailException e) {
ConsoleLogger.showError("Failed to create email with the given settings: "
+ StringUtils.formatException(e));
return;
}
String content = mailText;
// Generate an image?
File file = null;
if (Settings.generateImage) {
try {
file = generateImage(auth, plugin, newPass);
content = embedImageIntoEmailContent(file, email, content);
} catch (IOException | EmailException e) {
ConsoleLogger.showError("Unable to send new password as image for email "
+ auth.getEmail() + ": " + StringUtils.formatException(e));
}
}
sendEmail(content, email);
if (file != null) {
file.delete();
}
}
});
}
private static File generateImage(PlayerAuth auth, AuthMe plugin, String newPass) throws IOException {
ImageGenerator gen = new ImageGenerator(newPass);
File file = new File(plugin.getDataFolder() + File.separator + auth.getNickname() + "_new_pass.jpg");
ImageIO.write(gen.generateImage(), "jpg", file);
return file;
}
private static String embedImageIntoEmailContent(File image, HtmlEmail email, String content)
throws EmailException {
DataSource source = new FileDataSource(image);
String tag = email.embed(source, image.getName());
return content.replace("<image />", "<img src=\"cid:" + tag + "\">");
}
private static HtmlEmail initializeMail(PlayerAuth auth) throws EmailException {
String senderName;
if (Settings.getmailSenderName == null || Settings.getmailSenderName.isEmpty()) { if (Settings.getmailSenderName == null || Settings.getmailSenderName.isEmpty()) {
senderName = Settings.getmailAccount; senderName = Settings.getmailAccount;
} else { } else {
senderName = Settings.getmailSenderName; senderName = Settings.getmailSenderName;
} }
String senderMail = Settings.getmailAccount;
String mailPassword = Settings.getmailPassword;
final String sender = senderName;
final int port = Settings.getMailPort;
final String acc = Settings.getmailAccount;
final String subject = Settings.getMailSubject;
final String smtp = Settings.getmailSMTP;
final String password = Settings.getmailPassword;
final String mailText = Settings.getMailText.replace("<playername />", auth.getNickname()).replace("<servername />", plugin.getServer().getServerName()).replace("<generatedpass />", newPass);
final String mail = auth.getEmail();
Bukkit.getScheduler().runTaskAsynchronously(plugin, new Runnable() {
@Override
public void run() {
try {
Thread.currentThread().setContextClassLoader(this.getClass().getClassLoader());
HtmlEmail email = new HtmlEmail(); HtmlEmail email = new HtmlEmail();
email.setSmtpPort(port); email.setSmtpPort(Settings.getMailPort);
email.setHostName(smtp); email.setHostName(Settings.getmailSMTP);
email.addTo(mail); email.addTo(auth.getEmail());
email.setFrom(acc, sender); email.setFrom(senderMail, senderName);
email.setSubject(subject); email.setSubject(Settings.getMailSubject);
if (acc != null && !acc.isEmpty() && password != null && !password.isEmpty()) if (!StringUtils.isEmpty(senderMail) && !StringUtils.isEmpty(mailPassword)) {
email.setAuthenticator(new DefaultAuthenticator(acc, !Settings.emailOauth2Token.isEmpty() ? "" : password)); String password = !Settings.emailOauth2Token.isEmpty() ? "" : mailPassword;
email.setAuthenticator(new DefaultAuthenticator(senderMail, password));
}
return email;
}
private static boolean sendEmail(String content, HtmlEmail email) {
try {
email.setHtmlMsg(content);
email.setTextMsg(content);
} catch (EmailException e) {
ConsoleLogger.showError("Your email.html config contains an error and cannot be sent: "
+ StringUtils.formatException(e));
return false;
}
try {
email.send();
return true;
} catch (EmailException e) {
ConsoleLogger.showError("Failed to send a mail to " + email.getToAddresses() + ": " + e.getMessage());
return false;
}
}
private static String replaceMailTags(String mailText, AuthMe plugin, PlayerAuth auth, String newPass) {
return mailText
.replace("<playername />", auth.getNickname())
.replace("<servername />", plugin.getServer().getServerName())
.replace("<generatedpass />", newPass);
}
private static void setPropertiesForPort(int port, HtmlEmail email) throws EmailException {
switch (port) { switch (port) {
case 587: case 587:
email.setStartTLSEnabled(true); email.setStartTLSEnabled(true);
email.setStartTLSRequired(true); email.setStartTLSRequired(true);
if (!Settings.emailOauth2Token.isEmpty()) if (!Settings.emailOauth2Token.isEmpty()) {
{ if (Security.getProvider("Google OAuth2 Provider") == null) {
if (Security.getProvider("Google OAuth2 Provider") == null)
Security.addProvider(new OAuth2Provider()); Security.addProvider(new OAuth2Provider());
email.getMailSession().getProperties().setProperty("mail.smtp.starttls.enable", "true"); }
email.getMailSession().getProperties().setProperty("mail.smtp.starttls.required", "true");
email.getMailSession().getProperties().setProperty("mail.smtp.sasl.enable", "true"); Properties mailProperties = email.getMailSession().getProperties();
email.getMailSession().getProperties().setProperty("mail.smtp.sasl.mechanisms", "XOAUTH2"); mailProperties.setProperty("mail.smtp.starttls.enable", "true");
email.getMailSession().getProperties().setProperty(OAuth2SaslClientFactory.OAUTH_TOKEN_PROP, password); mailProperties.setProperty("mail.smtp.starttls.required", "true");
mailProperties.setProperty("mail.smtp.sasl.enable", "true");
mailProperties.setProperty("mail.smtp.sasl.mechanisms", "XOAUTH2");
mailProperties.setProperty(OAuth2SaslClientFactory.OAUTH_TOKEN_PROP, Settings.getmailPassword);
} }
break; break;
case 25: case 25:
@ -98,47 +163,6 @@ public class SendMailSSL {
email.setStartTLSEnabled(true); email.setStartTLSEnabled(true);
email.setSSLOnConnect(true); email.setSSLOnConnect(true);
email.setSSLCheckServerIdentity(true); email.setSSLCheckServerIdentity(true);
break;
}
String content = mailText;
// Generate an image ?
File file = null;
if (Settings.generateImage) {
try {
ImageGenerator gen = new ImageGenerator(newPass);
file = new File(plugin.getDataFolder() + File.separator + auth.getNickname() + "_new_pass.jpg");
ImageIO.write(gen.generateImage(), "jpg", file);
DataSource source = new FileDataSource(file);
String tag = email.embed(source, auth.getNickname() + "_new_pass.jpg");
content = content.replace("%image%", "<img src=\"cid:" + tag + "\">");
} catch (Exception e) {
ConsoleLogger.showError("Unable to send new password as image! Using normal text! Dest: " + mail);
} }
} }
try {
email.setHtmlMsg(content);
email.setTextMsg(content);
} catch (EmailException e)
{
ConsoleLogger.showError("Your email.html config contains some error and cannot be send!");
return;
}
try {
email.send();
} catch (Exception e) {
ConsoleLogger.showError("Fail to send a mail to " + mail + " cause " + e.getLocalizedMessage());
}
if (file != null)
//noinspection ResultOfMethodCallIgnored
file.delete();
} catch (Exception e) {
// Print the stack trace
e.printStackTrace();
ConsoleLogger.showError("Some error occurred while trying to send a email to " + mail);
}
}
});
}
} }

View File

@ -79,7 +79,7 @@ public final class Settings {
enableProtection, enableAntiBot, recallEmail, useWelcomeMessage, enableProtection, enableAntiBot, recallEmail, useWelcomeMessage,
broadcastWelcomeMessage, forceRegKick, forceRegLogin, broadcastWelcomeMessage, forceRegKick, forceRegLogin,
checkVeryGames, delayJoinLeaveMessages, noTeleport, applyBlindEffect, checkVeryGames, delayJoinLeaveMessages, noTeleport, applyBlindEffect,
kickPlayersBeforeStoping, kickPlayersBeforeStopping,
customAttributes, generateImage, isRemoveSpeedEnabled, preventOtherCase; customAttributes, generateImage, isRemoveSpeedEnabled, preventOtherCase;
public static String helpHeader, getNickRegex, getUnloggedinGroup, getMySQLHost, public static String helpHeader, getNickRegex, getUnloggedinGroup, getMySQLHost,
getMySQLPort, getMySQLUsername, getMySQLPassword, getMySQLDatabase, getMySQLPort, getMySQLUsername, getMySQLPassword, getMySQLDatabase,
@ -301,7 +301,7 @@ public final class Settings {
customAttributes = configFile.getBoolean("Hooks.customAttributes"); customAttributes = configFile.getBoolean("Hooks.customAttributes");
generateImage = configFile.getBoolean("Email.generateImage", false); generateImage = configFile.getBoolean("Email.generateImage", false);
preventOtherCase = configFile.getBoolean("settings.preventOtherCase", false); preventOtherCase = configFile.getBoolean("settings.preventOtherCase", false);
kickPlayersBeforeStoping = configFile.getBoolean("Security.stop.kickPlayersBeforeStoping", true); kickPlayersBeforeStopping = configFile.getBoolean("Security.stop.kickPlayersBeforeStopping", true);
emailOauth2Token = configFile.getString("Email.emailOauth2Token", ""); emailOauth2Token = configFile.getString("Email.emailOauth2Token", "");
// Load the welcome message // Load the welcome message
@ -730,8 +730,8 @@ public final class Settings {
ConsoleLogger.showError("Remove Email.mailText from config, we now use the email.html file"); ConsoleLogger.showError("Remove Email.mailText from config, we now use the email.html file");
} }
if (!contains("Security.stop.kickPlayersBeforeStoping")) { if (!contains("Security.stop.kickPlayersBeforeStopping")) {
set("Security.stop.kickPlayersBeforeStoping", true); set("Security.stop.kickPlayersBeforeStopping", true);
changes = true; changes = true;
} }

View File

@ -102,7 +102,7 @@ settings:
# - playername;127.0.0.1 # - playername;127.0.0.1
AllowedRestrictedUser: AllowedRestrictedUser:
- playername;127.0.0.1 - playername;127.0.0.1
# Should unregistered players be kicked immediatly? # Should unregistered players be kicked immediately?
kickNonRegistered: false kickNonRegistered: false
# Should players be kicked on wrong password? # Should players be kicked on wrong password?
kickOnWrongPassword: false kickOnWrongPassword: false
@ -150,7 +150,7 @@ settings:
maxJoinPerIp: 0 maxJoinPerIp: 0
# AuthMe will NEVER teleport players ! # AuthMe will NEVER teleport players !
noTeleport: false noTeleport: false
# Regex sintax for allowed Chars in passwords. # Regex syntax for allowed Chars in passwords.
allowedPasswordCharacters: '[\x21-\x7E]*' allowedPasswordCharacters: '[\x21-\x7E]*'
GameMode: GameMode:
# ForceSurvivalMode to player when join ? # ForceSurvivalMode to player when join ?
@ -227,7 +227,7 @@ settings:
# Does AuthMe need to enforce a /login after a successful registration? # Does AuthMe need to enforce a /login after a successful registration?
forceLoginAfterRegister: false forceLoginAfterRegister: false
unrestrictions: unrestrictions:
# below you can list all your account name, that # below you can list all account names that
# AuthMe will ignore for registration or login, configure it # AuthMe will ignore for registration or login, configure it
# at your own risk!! Remember that if you are going to add # at your own risk!! Remember that if you are going to add
# nickname with [], you have to delimit name with ' '. # nickname with [], you have to delimit name with ' '.
@ -257,8 +257,8 @@ settings:
delayJoinLeaveMessages: true delayJoinLeaveMessages: true
# Do we need to add potion effect Blinding before login/register? # Do we need to add potion effect Blinding before login/register?
applyBlindEffect: false applyBlindEffect: false
# Do we need to prevent people to login without another case ? # Do we need to prevent people to login with another case?
# Xephi is registered, also Xephi can login, but not XEPHI/xephi/XePhI # If Xephi is registered, then Xephi can login, but not XEPHI/xephi/XePhI
preventOtherCase: false preventOtherCase: false
ExternalBoardOptions: ExternalBoardOptions:
# MySQL column for the salt , needed for some forum/cms support # MySQL column for the salt , needed for some forum/cms support
@ -317,9 +317,9 @@ Security:
# Captcha length # Captcha length
captchaLength: 5 captchaLength: 5
stop: stop:
# Kick players before stoping the server, that allow us to save position of players, and all needed # Kick players before stopping the server, that allow us to save position of players, and all needed
# informations correctly without any corruption. # information correctly without any corruption.
kickPlayersBeforeStoping: true kickPlayersBeforeStopping: true
Converter: Converter:
Rakamak: Rakamak:
# Rakamak file name # Rakamak file name
@ -373,7 +373,7 @@ Hooks:
# Do we need to cache custom Attributes? # Do we need to cache custom Attributes?
customAttributes: false customAttributes: false
Purge: Purge:
# On Enable , does AuthMe need to purge automatically old accounts unused ? # If enabled, AuthMe automatically purges old, unused accounts
useAutoPurge: false useAutoPurge: false
# Number of Days an account become Unused # Number of Days an account become Unused
daysBeforeRemovePlayer: 60 daysBeforeRemovePlayer: 60