http://git-wip-us.apache.org/repos/asf/james-project/blob/52c18ef6/server/data/data-jdbc/src/main/java/org/apache/james/user/jdbc/AbstractJdbcUsersRepository.java ---------------------------------------------------------------------- diff --git a/server/data/data-jdbc/src/main/java/org/apache/james/user/jdbc/AbstractJdbcUsersRepository.java b/server/data/data-jdbc/src/main/java/org/apache/james/user/jdbc/AbstractJdbcUsersRepository.java index 8fc86c4..c6c02eb 100644 --- a/server/data/data-jdbc/src/main/java/org/apache/james/user/jdbc/AbstractJdbcUsersRepository.java +++ b/server/data/data-jdbc/src/main/java/org/apache/james/user/jdbc/AbstractJdbcUsersRepository.java @@ -96,25 +96,25 @@ import org.slf4j.LoggerFactory; public abstract class AbstractJdbcUsersRepository extends AbstractJamesUsersRepository { private static final Logger LOGGER = LoggerFactory.getLogger(AbstractJdbcUsersRepository.class); - protected Map<String, String> m_sqlParameters; + protected Map<String, String> sqlParameters; - private String m_sqlFileName; + private String sqlFileName; - private DataSource m_datasource; + private DataSource datasource; // Fetches all Users from the db. - private String m_getUsersSql; + private String getUsersSql; // This fetch a user by name, ensuring case-insensitive matching. - private String m_userByNameCaseInsensitiveSql; + private String userByNameCaseInsensitiveSql; // Insert, update and delete sql statements are not guaranteed // to be case-insensitive; this is handled in code. - private String m_insertUserSql; + private String insertUserSql; - private String m_updateUserSql; + private String updateUserSql; - private String m_deleteUserSql; + private String deleteUserSql; // The JDBCUtil helper class private JDBCUtil theJDBCUtil; @@ -213,12 +213,12 @@ public abstract class AbstractJdbcUsersRepository extends AbstractJamesUsersRepo /** * Set the DataSourceSelector * - * @param m_datasource + * @param datasource * the DataSourceSelector */ @Inject - public void setDatasource(DataSource m_datasource) { - this.m_datasource = m_datasource; + public void setDatasource(DataSource datasource) { + this.datasource = datasource; } /** @@ -259,31 +259,31 @@ public abstract class AbstractJdbcUsersRepository extends AbstractJamesUsersRepo InputStream sqlFile; try { - sqlFile = fileSystem.getResource(m_sqlFileName); + sqlFile = fileSystem.getResource(sqlFileName); } catch (Exception e) { LOGGER.error(e.getMessage(), e); throw e; } - LOGGER.debug("Reading SQL resources from: {}, section {}.", m_sqlFileName, getClass().getName()); + LOGGER.debug("Reading SQL resources from: {}, section {}.", sqlFileName, getClass().getName()); SqlResources sqlStatements = new SqlResources(); - sqlStatements.init(sqlFile, this.getClass().getName(), conn, m_sqlParameters); + sqlStatements.init(sqlFile, this.getClass().getName(), conn, sqlParameters); // Create the SQL Strings to use for this table. // Fetches all Users from the db. - m_getUsersSql = sqlStatements.getSqlString("select", true); + getUsersSql = sqlStatements.getSqlString("select", true); // Get a user by lowercase name. (optional) // If not provided, the entire list is iterated to find a user. - m_userByNameCaseInsensitiveSql = sqlStatements.getSqlString("selectByLowercaseName"); + userByNameCaseInsensitiveSql = sqlStatements.getSqlString("selectByLowercaseName"); // Insert, update and delete are not guaranteed to be // case-insensitive // Will always be called with correct case in username.. - m_insertUserSql = sqlStatements.getSqlString("insert", true); - m_updateUserSql = sqlStatements.getSqlString("update", true); - m_deleteUserSql = sqlStatements.getSqlString("delete", true); + insertUserSql = sqlStatements.getSqlString("insert", true); + updateUserSql = sqlStatements.getSqlString("update", true); + deleteUserSql = sqlStatements.getSqlString("delete", true); // Creates a single table with "username" the Primary Key. String createUserTableSql = sqlStatements.getSqlString("createTable", true); @@ -373,15 +373,15 @@ public abstract class AbstractJdbcUsersRepository extends AbstractJamesUsersRepo } // Build SqlParameters and get datasource name from URL parameters - m_sqlParameters = new HashMap<>(); + sqlParameters = new HashMap<>(); switch (urlParams.size()) { case 3: - m_sqlParameters.put("key", urlParams.get(2)); - m_sqlParameters.put("table", urlParams.get(1)); + sqlParameters.put("key", urlParams.get(2)); + sqlParameters.put("table", urlParams.get(1)); urlParams.get(0); break; case 2: - m_sqlParameters.put("table", urlParams.get(1)); + sqlParameters.put("table", urlParams.get(1)); urlParams.get(0); break; case 1: @@ -391,10 +391,10 @@ public abstract class AbstractJdbcUsersRepository extends AbstractJamesUsersRepo throw new ConfigurationException("Malformed destinationURL - " + "Must be of the format \"db://<data-source>[/<table>[/<key>]]\"."); } - LOGGER.debug("Parsed URL: table = '{}', key = '{}'", m_sqlParameters.get("table"), m_sqlParameters.get("key")); + LOGGER.debug("Parsed URL: table = '{}', key = '{}'", sqlParameters.get("table"), sqlParameters.get("key")); // Get the SQL file location - m_sqlFileName = configuration.getString("sqlFile", null); + sqlFileName = configuration.getString("sqlFile", null); // Get other sql parameters from the configuration object, // if any. @@ -403,7 +403,7 @@ public abstract class AbstractJdbcUsersRepository extends AbstractJamesUsersRepo String rawName = paramIt.next(); String paramName = paramIt.next().substring("sqlParameters.[@".length(), rawName.length() - 1); String paramValue = configuration.getString(rawName); - m_sqlParameters.put(paramName, paramValue); + sqlParameters.put(paramName, paramValue); } } @@ -448,7 +448,7 @@ public abstract class AbstractJdbcUsersRepository extends AbstractJamesUsersRepo try { conn = openConnection(); // Get a ResultSet containing all users. - getUsersStatement = conn.prepareStatement(m_getUsersSql); + getUsersStatement = conn.prepareStatement(getUsersSql); rsUsers = getUsersStatement.executeQuery(); // Loop through and build a User for every row. @@ -483,7 +483,7 @@ public abstract class AbstractJdbcUsersRepository extends AbstractJamesUsersRepo try { conn = openConnection(); // Get a PreparedStatement for the insert. - addUserStatement = conn.prepareStatement(m_insertUserSql); + addUserStatement = conn.prepareStatement(insertUserSql); setUserForInsertStatement(user, addUserStatement); @@ -513,7 +513,7 @@ public abstract class AbstractJdbcUsersRepository extends AbstractJamesUsersRepo // Delete from the database. try { conn = openConnection(); - removeUserStatement = conn.prepareStatement(m_deleteUserSql); + removeUserStatement = conn.prepareStatement(deleteUserSql); removeUserStatement.setString(1, username); removeUserStatement.execute(); } catch (SQLException sqlExc) { @@ -538,7 +538,7 @@ public abstract class AbstractJdbcUsersRepository extends AbstractJamesUsersRepo // Update the database. try { conn = openConnection(); - updateUserStatement = conn.prepareStatement(m_updateUserSql); + updateUserStatement = conn.prepareStatement(updateUserSql); setUserForUpdateStatement(user, updateUserStatement); updateUserStatement.execute(); } catch (SQLException sqlExc) { @@ -592,7 +592,7 @@ public abstract class AbstractJdbcUsersRepository extends AbstractJamesUsersRepo protected User getUserByName(String name, boolean ignoreCase) throws UsersRepositoryException { // See if this statement has been set, if not, use // simple superclass method. - if (m_userByNameCaseInsensitiveSql == null) { + if (userByNameCaseInsensitiveSql == null) { return getUserByNameIterating(name, ignoreCase); } @@ -604,7 +604,7 @@ public abstract class AbstractJdbcUsersRepository extends AbstractJamesUsersRepo try { conn = openConnection(); // Get a ResultSet containing all users. - String sql = m_userByNameCaseInsensitiveSql; + String sql = userByNameCaseInsensitiveSql; getUsersStatement = conn.prepareStatement(sql); getUsersStatement.setString(1, name.toLowerCase(Locale.US)); @@ -688,7 +688,7 @@ public abstract class AbstractJdbcUsersRepository extends AbstractJamesUsersRepo * @throws SQLException */ private Connection openConnection() throws SQLException { - return m_datasource.getConnection(); + return datasource.getConnection(); } }
http://git-wip-us.apache.org/repos/asf/james-project/blob/52c18ef6/server/data/data-ldap/src/main/java/org/apache/james/user/ldap/ReadOnlyLDAPUser.java ---------------------------------------------------------------------- diff --git a/server/data/data-ldap/src/main/java/org/apache/james/user/ldap/ReadOnlyLDAPUser.java b/server/data/data-ldap/src/main/java/org/apache/james/user/ldap/ReadOnlyLDAPUser.java index 3f35362..9156016 100644 --- a/server/data/data-ldap/src/main/java/org/apache/james/user/ldap/ReadOnlyLDAPUser.java +++ b/server/data/data-ldap/src/main/java/org/apache/james/user/ldap/ReadOnlyLDAPUser.java @@ -54,18 +54,18 @@ public class ReadOnlyLDAPUser implements User, Serializable { * <code>"myorg.com"</code>, the user's email address will be * <code>"john.bold@myorg.com"</code>. */ - private String _userName; + private String userName; /** * The distinguished name of the user-record in the LDAP directory. */ - private String _userDN; + private String userDN; /** * The context for the LDAP server from which to retrieve the * user's details. */ - private LdapContext _ldapContext = null; + private LdapContext ldapContext = null; /** * Creates a new instance of ReadOnlyLDAPUser. @@ -95,9 +95,9 @@ public class ReadOnlyLDAPUser implements User, Serializable { */ public ReadOnlyLDAPUser(String userName, String userDN, LdapContext ldapContext) { this(); - _userName = userName; - _userDN = userDN; - _ldapContext = ldapContext; + this.userName = userName; + this.userDN = userDN; + this.ldapContext = ldapContext; } /** @@ -108,7 +108,7 @@ public class ReadOnlyLDAPUser implements User, Serializable { * @return The user's identifier or name. */ public String getUserName() { - return _userName; + return userName; } /** @@ -138,10 +138,10 @@ public class ReadOnlyLDAPUser implements User, Serializable { boolean result = false; LdapContext ldapContext = null; try { - ldapContext = _ldapContext.newInstance(null); + ldapContext = this.ldapContext.newInstance(null); ldapContext.addToEnvironment(Context.SECURITY_AUTHENTICATION, LdapConstants.SECURITY_AUTHENTICATION_SIMPLE); - ldapContext.addToEnvironment(Context.SECURITY_PRINCIPAL, _userDN); + ldapContext.addToEnvironment(Context.SECURITY_PRINCIPAL, userDN); ldapContext.addToEnvironment(Context.SECURITY_CREDENTIALS, password); ldapContext.reconnect(null); result = true; http://git-wip-us.apache.org/repos/asf/james-project/blob/52c18ef6/server/data/data-library/src/main/java/org/apache/james/repository/file/AbstractFileRepository.java ---------------------------------------------------------------------- diff --git a/server/data/data-library/src/main/java/org/apache/james/repository/file/AbstractFileRepository.java b/server/data/data-library/src/main/java/org/apache/james/repository/file/AbstractFileRepository.java index bd8a81c..bd2dfa1 100644 --- a/server/data/data-library/src/main/java/org/apache/james/repository/file/AbstractFileRepository.java +++ b/server/data/data-library/src/main/java/org/apache/james/repository/file/AbstractFileRepository.java @@ -54,13 +54,13 @@ public abstract class AbstractFileRepository implements Repository, Configurable protected static final char[] HEX_DIGITS = new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; - protected String m_extension; + protected String extension; - protected String m_name; + protected String name; - protected FilenameFilter m_filter; + protected FilenameFilter filter; - protected File m_baseDirectory; + protected File baseDirectory; private FileSystem fileSystem; @@ -85,37 +85,37 @@ public abstract class AbstractFileRepository implements Repository, Configurable File directory; try { - directory = m_baseDirectory.getCanonicalFile(); + directory = baseDirectory.getCanonicalFile(); } catch (IOException ioe) { - throw new ConfigurationException("Unable to form canonical representation of " + m_baseDirectory); + throw new ConfigurationException("Unable to form canonical representation of " + baseDirectory); } - m_name = "Repository"; - String m_postfix = getExtensionDecorator(); - m_extension = "." + m_name + m_postfix; - m_filter = new ExtensionFileFilter(m_extension); + name = "Repository"; + String postfix = getExtensionDecorator(); + extension = "." + name + postfix; + filter = new ExtensionFileFilter(extension); // m_filter = new NumberedRepositoryFileFilter(getExtensionDecorator()); FileUtils.forceMkdir(directory); - LOGGER.info("{} opened in {}", getClass().getName(), m_baseDirectory); + LOGGER.info("{} opened in {}", getClass().getName(), baseDirectory); // We will look for all numbered repository files in this // directory and rename them to non-numbered repositories, // logging all the way. - FilenameFilter num_filter = new NumberedRepositoryFileFilter(getExtensionDecorator()); - final String[] names = directory.list(num_filter); + FilenameFilter numFilter = new NumberedRepositoryFileFilter(getExtensionDecorator()); + final String[] names = directory.list(numFilter); for (String origFilename : names) { // This needs to handle (skip over) the possible repository // numbers - int pos = origFilename.length() - m_postfix.length(); + int pos = origFilename.length() - postfix.length(); while (pos >= 1 && Character.isDigit(origFilename.charAt(pos - 1))) { pos--; } - pos -= ".".length() + m_name.length(); - String newFilename = origFilename.substring(0, pos) + m_extension; + pos -= ".".length() + name.length(); + String newFilename = origFilename.substring(0, pos) + extension; File origFile = new File(directory, origFilename); File newFile = new File(directory, newFilename); @@ -145,7 +145,7 @@ public abstract class AbstractFileRepository implements Repository, Configurable } try { - m_baseDirectory = fileSystem.getFile(destination); + baseDirectory = fileSystem.getFile(destination); } catch (FileNotFoundException e) { throw new ConfigurationException("Unable to acces destination " + destination, e); } @@ -177,7 +177,7 @@ public abstract class AbstractFileRepository implements Repository, Configurable child.setFileSystem(fileSystem); try { - child.setDestination(m_baseDirectory.getAbsolutePath() + File.pathSeparatorChar + childName + File.pathSeparator); + child.setDestination(baseDirectory.getAbsolutePath() + File.pathSeparatorChar + childName + File.pathSeparator); } catch (ConfigurationException ce) { throw new RuntimeException("Cannot set destination for child child " + "repository " + childName + " : " + ce); } @@ -189,7 +189,7 @@ public abstract class AbstractFileRepository implements Repository, Configurable } if (DEBUG && LOGGER.isDebugEnabled()) { - LOGGER.debug("Child repository of " + m_name + " created in " + m_baseDirectory + File.pathSeparatorChar + childName + File.pathSeparator); + LOGGER.debug("Child repository of " + name + " created in " + baseDirectory + File.pathSeparatorChar + childName + File.pathSeparator); } return child; @@ -282,8 +282,8 @@ public abstract class AbstractFileRepository implements Repository, Configurable * Returns the list of used keys. */ public Iterator<String> list() { - final File storeDir = new File(m_baseDirectory.getAbsolutePath()); - final String[] names = storeDir.list(m_filter); + final File storeDir = new File(baseDirectory.getAbsolutePath()); + final String[] names = storeDir.list(filter); return Arrays.stream(names) .map(this::decode) @@ -313,10 +313,10 @@ public abstract class AbstractFileRepository implements Repository, Configurable } StringBuilder result = new StringBuilder(); - result.append(m_baseDirectory.getAbsolutePath()); + result.append(baseDirectory.getAbsolutePath()); result.append(File.separator); result.append(buffer); - result.append(m_extension); + result.append(extension); return result.toString(); } @@ -330,7 +330,7 @@ public abstract class AbstractFileRepository implements Repository, Configurable * @return key a String which can be used to retrieve the filename */ protected String decode(String filename) { - filename = filename.substring(0, filename.length() - m_extension.length()); + filename = filename.substring(0, filename.length() - extension.length()); final int size = filename.length(); final byte[] bytes = new byte[size >>> 1]; http://git-wip-us.apache.org/repos/asf/james-project/blob/52c18ef6/server/data/data-library/src/main/java/org/apache/james/repository/file/ClassLoaderObjectInputStream.java ---------------------------------------------------------------------- diff --git a/server/data/data-library/src/main/java/org/apache/james/repository/file/ClassLoaderObjectInputStream.java b/server/data/data-library/src/main/java/org/apache/james/repository/file/ClassLoaderObjectInputStream.java index c7c256c..4bda697 100644 --- a/server/data/data-library/src/main/java/org/apache/james/repository/file/ClassLoaderObjectInputStream.java +++ b/server/data/data-library/src/main/java/org/apache/james/repository/file/ClassLoaderObjectInputStream.java @@ -29,15 +29,15 @@ import java.io.ObjectStreamClass; * Avalon components that are juggling many classloaders. */ public class ClassLoaderObjectInputStream extends ObjectInputStream { - private final ClassLoader m_classLoader; + private final ClassLoader classLoader; public ClassLoaderObjectInputStream(ClassLoader classLoader, InputStream inputStream) throws IOException { super(inputStream); - m_classLoader = classLoader; + this.classLoader = classLoader; } protected Class<?> resolveClass(ObjectStreamClass objectStreamClass) throws IOException, ClassNotFoundException { - final Class<?> clazz = Class.forName(objectStreamClass.getName(), false, m_classLoader); + final Class<?> clazz = Class.forName(objectStreamClass.getName(), false, classLoader); if (null != clazz) { return clazz; // the classloader knows of the class http://git-wip-us.apache.org/repos/asf/james-project/blob/52c18ef6/server/data/data-library/src/main/java/org/apache/james/repository/file/ExtensionFileFilter.java ---------------------------------------------------------------------- diff --git a/server/data/data-library/src/main/java/org/apache/james/repository/file/ExtensionFileFilter.java b/server/data/data-library/src/main/java/org/apache/james/repository/file/ExtensionFileFilter.java index 2820a4a..c052c19 100644 --- a/server/data/data-library/src/main/java/org/apache/james/repository/file/ExtensionFileFilter.java +++ b/server/data/data-library/src/main/java/org/apache/james/repository/file/ExtensionFileFilter.java @@ -41,17 +41,17 @@ import java.util.Arrays; * </pre> */ public class ExtensionFileFilter implements FilenameFilter { - private final String[] m_extensions; + private final String[] extensions; public ExtensionFileFilter(String[] extensions) { - m_extensions = extensions; + this.extensions = extensions; } public ExtensionFileFilter(String extension) { - m_extensions = new String[] { extension }; + extensions = new String[] { extension }; } public boolean accept(File file, String name) { - return Arrays.stream(m_extensions).anyMatch(name::endsWith); + return Arrays.stream(extensions).anyMatch(name::endsWith); } } http://git-wip-us.apache.org/repos/asf/james-project/blob/52c18ef6/server/data/data-library/src/main/java/org/apache/james/rrt/lib/RecipientRewriteTableUtil.java ---------------------------------------------------------------------- diff --git a/server/data/data-library/src/main/java/org/apache/james/rrt/lib/RecipientRewriteTableUtil.java b/server/data/data-library/src/main/java/org/apache/james/rrt/lib/RecipientRewriteTableUtil.java index 19a5db6..75c4054 100644 --- a/server/data/data-library/src/main/java/org/apache/james/rrt/lib/RecipientRewriteTableUtil.java +++ b/server/data/data-library/src/main/java/org/apache/james/rrt/lib/RecipientRewriteTableUtil.java @@ -115,18 +115,18 @@ public class RecipientRewriteTableUtil { * @return the substituted string */ private static String substituteSubString(String input, String find, String replace) { - int find_length = find.length(); - int replace_length = replace.length(); + int findLength = find.length(); + int replaceLength = replace.length(); StringBuilder output = new StringBuilder(input); int index = input.indexOf(find); int outputOffset = 0; while (index > -1) { - output.replace(index + outputOffset, index + outputOffset + find_length, replace); - outputOffset = outputOffset + (replace_length - find_length); + output.replace(index + outputOffset, index + outputOffset + findLength, replace); + outputOffset = outputOffset + (replaceLength - findLength); - index = input.indexOf(find, index + find_length); + index = input.indexOf(find, index + findLength); } String result = output.toString(); http://git-wip-us.apache.org/repos/asf/james-project/blob/52c18ef6/server/data/data-library/src/test/java/org/apache/james/domainlist/lib/AbstractDomainListTest.java ---------------------------------------------------------------------- diff --git a/server/data/data-library/src/test/java/org/apache/james/domainlist/lib/AbstractDomainListTest.java b/server/data/data-library/src/test/java/org/apache/james/domainlist/lib/AbstractDomainListTest.java index 03a0555..658c68c 100644 --- a/server/data/data-library/src/test/java/org/apache/james/domainlist/lib/AbstractDomainListTest.java +++ b/server/data/data-library/src/test/java/org/apache/james/domainlist/lib/AbstractDomainListTest.java @@ -39,12 +39,12 @@ public abstract class AbstractDomainListTest { private static final Logger LOGGER = LoggerFactory.getLogger(AbstractDomainListTest.class); - private final String DOMAIN_1 = "domain1.tld"; - private final String DOMAIN_2 = "domain2.tld"; - private final String DOMAIN_3 = "domain3.tld"; - private final String DOMAIN_4 = "domain4.tld"; - private final String DOMAIN_5 = "domain5.tld"; - private final String DOMAIN_UPPER_5 = "Domain5.tld"; + private static final String DOMAIN_1 = "domain1.tld"; + private static final String DOMAIN_2 = "domain2.tld"; + private static final String DOMAIN_3 = "domain3.tld"; + private static final String DOMAIN_4 = "domain4.tld"; + private static final String DOMAIN_5 = "domain5.tld"; + private static final String DOMAIN_UPPER_5 = "Domain5.tld"; private DomainList domainList; @@ -117,21 +117,21 @@ public abstract class AbstractDomainListTest { } @Test - public void ContainsShouldReturnFalseWhenDomainIsRemoved() throws DomainListException { + public void containsShouldReturnFalseWhenDomainIsRemoved() throws DomainListException { domainList.addDomain(DOMAIN_1); domainList.removeDomain(DOMAIN_1); assertThat(domainList.containsDomain(DOMAIN_1)).isFalse(); } @Test - public void RemoveShouldRemoveDomainsUsingUpperCases() throws DomainListException { + public void removeShouldRemoveDomainsUsingUpperCases() throws DomainListException { domainList.addDomain(DOMAIN_UPPER_5); domainList.removeDomain(DOMAIN_UPPER_5); assertThat(domainList.containsDomain(DOMAIN_UPPER_5)).isFalse(); } @Test - public void RemoveShouldRemoveDomainsUsingLowerCases() throws DomainListException { + public void removeShouldRemoveDomainsUsingLowerCases() throws DomainListException { domainList.addDomain(DOMAIN_UPPER_5); domainList.removeDomain(DOMAIN_5); assertThat(domainList.containsDomain(DOMAIN_UPPER_5)).isFalse(); http://git-wip-us.apache.org/repos/asf/james-project/blob/52c18ef6/server/data/data-library/src/test/java/org/apache/james/mailrepository/mock/MockMailRepositoryStore.java ---------------------------------------------------------------------- diff --git a/server/data/data-library/src/test/java/org/apache/james/mailrepository/mock/MockMailRepositoryStore.java b/server/data/data-library/src/test/java/org/apache/james/mailrepository/mock/MockMailRepositoryStore.java index 707a2c9..6d16b4c 100644 --- a/server/data/data-library/src/test/java/org/apache/james/mailrepository/mock/MockMailRepositoryStore.java +++ b/server/data/data-library/src/test/java/org/apache/james/mailrepository/mock/MockMailRepositoryStore.java @@ -29,10 +29,10 @@ import org.apache.james.mailrepository.api.MailRepositoryStore; public class MockMailRepositoryStore implements MailRepositoryStore { - final Map<String, MailRepository> m_storedObjectMap = new HashMap<>(); + final Map<String, MailRepository> storedObjectMap = new HashMap<>(); public void add(String url, MailRepository obj) { - m_storedObjectMap.put(url, obj); + storedObjectMap.put(url, obj); } @Override @@ -42,12 +42,12 @@ public class MockMailRepositoryStore implements MailRepositoryStore { private MailRepository get(String key) { System.out.println(key); - return m_storedObjectMap.get(key); + return storedObjectMap.get(key); } @Override public List<String> getUrls() { - return new ArrayList<>(m_storedObjectMap.keySet()); + return new ArrayList<>(storedObjectMap.keySet()); } } http://git-wip-us.apache.org/repos/asf/james-project/blob/52c18ef6/server/data/data-library/src/test/java/org/apache/james/user/lib/UsersRepositoryManagementTest.java ---------------------------------------------------------------------- diff --git a/server/data/data-library/src/test/java/org/apache/james/user/lib/UsersRepositoryManagementTest.java b/server/data/data-library/src/test/java/org/apache/james/user/lib/UsersRepositoryManagementTest.java index d3e85d8..7ffa5fa 100644 --- a/server/data/data-library/src/test/java/org/apache/james/user/lib/UsersRepositoryManagementTest.java +++ b/server/data/data-library/src/test/java/org/apache/james/user/lib/UsersRepositoryManagementTest.java @@ -35,44 +35,44 @@ import org.junit.Test; */ public class UsersRepositoryManagementTest { - private InMemoryUsersRepository m_mockUsersRepository; - private UsersRepositoryManagement m_userManagement; + private InMemoryUsersRepository mockUsersRepository; + private UsersRepositoryManagement userManagement; @Before public void setUp() throws Exception { - m_mockUsersRepository = new InMemoryUsersRepository(); + mockUsersRepository = new InMemoryUsersRepository(); - m_userManagement = new UsersRepositoryManagement(); - m_userManagement.setUsersRepository(m_mockUsersRepository); + userManagement = new UsersRepositoryManagement(); + userManagement.setUsersRepository(mockUsersRepository); } @Test public void testUserCount() throws Exception { - assertEquals("no user yet", 0, m_userManagement.countUsers()); - m_mockUsersRepository.addUser("testCount1", "testCount"); - assertEquals("1 user", 1, m_userManagement.countUsers()); - m_mockUsersRepository.addUser("testCount2", "testCount"); - assertEquals("2 users", 2, m_userManagement.countUsers()); - m_mockUsersRepository.removeUser("testCount1"); - assertEquals("1 user", 1, m_userManagement.countUsers()); + assertEquals("no user yet", 0, userManagement.countUsers()); + mockUsersRepository.addUser("testCount1", "testCount"); + assertEquals("1 user", 1, userManagement.countUsers()); + mockUsersRepository.addUser("testCount2", "testCount"); + assertEquals("2 users", 2, userManagement.countUsers()); + mockUsersRepository.removeUser("testCount1"); + assertEquals("1 user", 1, userManagement.countUsers()); } @Test public void testAddUserAndVerify() throws Exception { - m_mockUsersRepository.addUser("testCount1", "testCount"); - assertFalse("user not there", m_userManagement.verifyExists("testNotAdded")); - assertTrue("user is there", m_userManagement.verifyExists("testCount1")); - m_mockUsersRepository.removeUser("testCount1"); - assertFalse("user not there", m_userManagement.verifyExists("testCount1")); + mockUsersRepository.addUser("testCount1", "testCount"); + assertFalse("user not there", userManagement.verifyExists("testNotAdded")); + assertTrue("user is there", userManagement.verifyExists("testCount1")); + mockUsersRepository.removeUser("testCount1"); + assertFalse("user not there", userManagement.verifyExists("testCount1")); } @Test public void testDelUser() throws Exception { - m_mockUsersRepository.addUser("testDel", "test"); - assertFalse("user not there", m_userManagement.verifyExists("testNotDeletable")); - assertTrue("user is there", m_userManagement.verifyExists("testDel")); - m_mockUsersRepository.removeUser("testDel"); - assertFalse("user no longer there", m_userManagement.verifyExists("testDel")); + mockUsersRepository.addUser("testDel", "test"); + assertFalse("user not there", userManagement.verifyExists("testNotDeletable")); + assertTrue("user is there", userManagement.verifyExists("testDel")); + mockUsersRepository.removeUser("testDel"); + assertFalse("user no longer there", userManagement.verifyExists("testDel")); } @Test @@ -82,10 +82,10 @@ public class UsersRepositoryManagementTest { List<String> users = Arrays.asList(usersArray); for (String user : users) { - m_mockUsersRepository.addUser(user, "test"); + mockUsersRepository.addUser(user, "test"); } - String[] userNames = m_userManagement.listAllUsers(); + String[] userNames = userManagement.listAllUsers(); assertEquals("user count", users.size(), userNames.length); for (String user : userNames) { @@ -98,22 +98,22 @@ public class UsersRepositoryManagementTest { @Test public void testSetPassword() throws Exception { - m_userManagement.addUser("testPwdUser", "pwd1"); + userManagement.addUser("testPwdUser", "pwd1"); - assertTrue("initial password", m_mockUsersRepository.test("testPwdUser", "pwd1")); + assertTrue("initial password", mockUsersRepository.test("testPwdUser", "pwd1")); // set empty pwd - m_userManagement.setPassword("testPwdUser", ""); - assertTrue("password changed to empty", m_mockUsersRepository.test("testPwdUser", "")); + userManagement.setPassword("testPwdUser", ""); + assertTrue("password changed to empty", mockUsersRepository.test("testPwdUser", "")); // change pwd - m_userManagement.setPassword("testPwdUser", "pwd2"); - assertTrue("password not changed to pwd2", m_mockUsersRepository.test("testPwdUser", "pwd2")); + userManagement.setPassword("testPwdUser", "pwd2"); + assertTrue("password not changed to pwd2", mockUsersRepository.test("testPwdUser", "pwd2")); // assure case sensitivity - m_userManagement.setPassword("testPwdUser", "pWD2"); - assertFalse("password no longer pwd2", m_mockUsersRepository.test("testPwdUser", "pwd2")); - assertTrue("password changed to pWD2", m_mockUsersRepository.test("testPwdUser", "pWD2")); + userManagement.setPassword("testPwdUser", "pWD2"); + assertFalse("password no longer pwd2", mockUsersRepository.test("testPwdUser", "pwd2")); + assertTrue("password changed to pWD2", mockUsersRepository.test("testPwdUser", "pWD2")); } } http://git-wip-us.apache.org/repos/asf/james-project/blob/52c18ef6/server/data/data-library/src/test/java/org/apache/james/user/lib/mock/InMemoryUsersRepository.java ---------------------------------------------------------------------- diff --git a/server/data/data-library/src/test/java/org/apache/james/user/lib/mock/InMemoryUsersRepository.java b/server/data/data-library/src/test/java/org/apache/james/user/lib/mock/InMemoryUsersRepository.java index 0409af6..6053070 100644 --- a/server/data/data-library/src/test/java/org/apache/james/user/lib/mock/InMemoryUsersRepository.java +++ b/server/data/data-library/src/test/java/org/apache/james/user/lib/mock/InMemoryUsersRepository.java @@ -33,7 +33,7 @@ import org.apache.james.user.lib.model.DefaultUser; @SuppressWarnings("deprecation") public class InMemoryUsersRepository extends AbstractJamesUsersRepository { - private final HashMap<String, User> m_users = new HashMap<>(); + private final HashMap<String, User> users = new HashMap<>(); /** * force the repository to hold implementations of JamesUser interface, * instead of User JamesUser is _not_ required as of the UsersRepository @@ -41,10 +41,10 @@ public class InMemoryUsersRepository extends AbstractJamesUsersRepository { * UsersRepository while at the same time expecting it to hold JamesUsers * (like in RemoteManagerHandler) */ - private boolean m_forceUseJamesUser = false; + private boolean forceUseJamesUser = false; public void setForceUseJamesUser() { - m_forceUseJamesUser = true; + forceUseJamesUser = true; } @Override @@ -52,29 +52,29 @@ public class InMemoryUsersRepository extends AbstractJamesUsersRepository { if (ignoreCase) { return getUserByNameCaseInsensitive(name); } else { - return m_users.get(name); + return users.get(name); } } public User getUserByNameCaseInsensitive(String name) { - return m_users.get(name.toLowerCase(Locale.US)); + return users.get(name.toLowerCase(Locale.US)); } public String getRealName(String name) { if (ignoreCase) { - return m_users.get(name.toLowerCase(Locale.US)) != null ? - m_users.get(name.toLowerCase(Locale.US)).getUserName() : null; + return users.get(name.toLowerCase(Locale.US)) != null ? + users.get(name.toLowerCase(Locale.US)).getUserName() : null; } else { - return m_users.get(name) != null ? name : null; + return users.get(name) != null ? name : null; } } @Override public void removeUser(String name) throws UsersRepositoryException { - if (!m_users.containsKey(name)) { + if (!users.containsKey(name)) { throw new UsersRepositoryException("No such user"); } else { - m_users.remove(name); + users.remove(name); } } @@ -83,7 +83,7 @@ public class InMemoryUsersRepository extends AbstractJamesUsersRepository { if (ignoreCase) { return containsCaseInsensitive(name); } else { - return m_users.containsKey(name); + return users.containsKey(name); } } @@ -99,11 +99,11 @@ public class InMemoryUsersRepository extends AbstractJamesUsersRepository { @Override public int countUsers() throws UsersRepositoryException { - return m_users.size(); + return users.size(); } protected List<String> listUserNames() { - Iterator<User> users = m_users.values().iterator(); + Iterator<User> users = this.users.values().iterator(); List<String> userNames = new LinkedList<>(); while (users.hasNext()) { User user = users.next(); @@ -120,19 +120,19 @@ public class InMemoryUsersRepository extends AbstractJamesUsersRepository { @Override protected void doAddUser(User user) throws UsersRepositoryException { - if (m_forceUseJamesUser && user instanceof DefaultUser) { + if (forceUseJamesUser && user instanceof DefaultUser) { DefaultUser aUser = (DefaultUser) user; user = new DefaultJamesUser(aUser.getUserName(), aUser.getHashedPassword(), aUser.getHashAlgorithm()); } String key = user.getUserName(); - m_users.put(key, user); + users.put(key, user); } @Override protected void doUpdateUser(User user) throws UsersRepositoryException { - if (m_users.containsKey(user.getUserName())) { - m_users.put(user.getUserName(), user); + if (users.containsKey(user.getUserName())) { + users.put(user.getUserName(), user); } else { throw new UsersRepositoryException("No such user"); } http://git-wip-us.apache.org/repos/asf/james-project/blob/52c18ef6/server/dns-service/dnsservice-dnsjava/src/main/java/org/apache/james/dnsservice/dnsjava/DNSJavaService.java ---------------------------------------------------------------------- diff --git a/server/dns-service/dnsservice-dnsjava/src/main/java/org/apache/james/dnsservice/dnsjava/DNSJavaService.java b/server/dns-service/dnsservice-dnsjava/src/main/java/org/apache/james/dnsservice/dnsjava/DNSJavaService.java index 1ff0e96..0230768 100644 --- a/server/dns-service/dnsservice-dnsjava/src/main/java/org/apache/james/dnsservice/dnsjava/DNSJavaService.java +++ b/server/dns-service/dnsservice-dnsjava/src/main/java/org/apache/james/dnsservice/dnsjava/DNSJavaService.java @@ -422,9 +422,9 @@ public class DNSJavaService implements DNSService, DNSServiceMBean, Configurable private static String allowIPLiteral(String host) { if ((host.charAt(host.length() - 1) == '.')) { - String possible_ip_literal = host.substring(0, host.length() - 1); - if (org.xbill.DNS.Address.isDottedQuad(possible_ip_literal)) { - host = possible_ip_literal; + String possibleIpLiteral = host.substring(0, host.length() - 1); + if (org.xbill.DNS.Address.isDottedQuad(possibleIpLiteral)) { + host = possibleIpLiteral; } } return host; http://git-wip-us.apache.org/repos/asf/james-project/blob/52c18ef6/server/mailet/integration-testing/src/test/java/org/apache/james/mailets/crypto/SMIMESignIntegrationTest.java ---------------------------------------------------------------------- diff --git a/server/mailet/integration-testing/src/test/java/org/apache/james/mailets/crypto/SMIMESignIntegrationTest.java b/server/mailet/integration-testing/src/test/java/org/apache/james/mailets/crypto/SMIMESignIntegrationTest.java index 3870876..3bf2eb6 100644 --- a/server/mailet/integration-testing/src/test/java/org/apache/james/mailets/crypto/SMIMESignIntegrationTest.java +++ b/server/mailet/integration-testing/src/test/java/org/apache/james/mailets/crypto/SMIMESignIntegrationTest.java @@ -126,7 +126,7 @@ public class SMIMESignIntegrationTest { } @Test - public void NonAuthenticatedMessagesShouldNotBeSigned() throws Exception { + public void nonAuthenticatedMessagesShouldNotBeSigned() throws Exception { messageSender.connect(LOCALHOST_IP, SMTP_SECURE_PORT) .sendMessage(FROM, RECIPIENT) .awaitSent(awaitOneMinute); http://git-wip-us.apache.org/repos/asf/james-project/blob/52c18ef6/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/RemoteDelivery.java ---------------------------------------------------------------------- diff --git a/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/RemoteDelivery.java b/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/RemoteDelivery.java index 43307e3..e75b510 100644 --- a/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/RemoteDelivery.java +++ b/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/RemoteDelivery.java @@ -38,10 +38,10 @@ import org.apache.james.queue.api.MailPrioritySupport; import org.apache.james.queue.api.MailQueue; import org.apache.james.queue.api.MailQueue.MailQueueException; import org.apache.james.queue.api.MailQueueFactory; -import org.apache.james.transport.mailets.remoteDelivery.Bouncer; -import org.apache.james.transport.mailets.remoteDelivery.DeliveryRunnable; -import org.apache.james.transport.mailets.remoteDelivery.RemoteDeliveryConfiguration; -import org.apache.james.transport.mailets.remoteDelivery.RemoteDeliverySocketFactory; +import org.apache.james.transport.mailets.remote.delivery.Bouncer; +import org.apache.james.transport.mailets.remote.delivery.DeliveryRunnable; +import org.apache.james.transport.mailets.remote.delivery.RemoteDeliveryConfiguration; +import org.apache.james.transport.mailets.remote.delivery.RemoteDeliverySocketFactory; import org.apache.mailet.Mail; import org.apache.mailet.base.GenericMailet; import org.slf4j.Logger; @@ -122,7 +122,7 @@ import com.google.common.collect.HashMultimap; public class RemoteDelivery extends GenericMailet { private static final Logger LOGGER = LoggerFactory.getLogger(RemoteDelivery.class); - public enum THREAD_STATE { + public enum ThreadState { START_THREADS, DO_NOT_START_THREADS } @@ -134,7 +134,7 @@ public class RemoteDelivery extends GenericMailet { private final MailQueueFactory queueFactory; private final MetricFactory metricFactory; private final AtomicBoolean isDestroyed; - private final THREAD_STATE startThreads; + private final ThreadState startThreads; private MailQueue queue; private RemoteDeliveryConfiguration configuration; @@ -142,10 +142,10 @@ public class RemoteDelivery extends GenericMailet { @Inject public RemoteDelivery(DNSService dnsServer, DomainList domainList, MailQueueFactory queueFactory, MetricFactory metricFactory) { - this(dnsServer, domainList, queueFactory, metricFactory, THREAD_STATE.START_THREADS); + this(dnsServer, domainList, queueFactory, metricFactory, ThreadState.START_THREADS); } - public RemoteDelivery(DNSService dnsServer, DomainList domainList, MailQueueFactory queueFactory, MetricFactory metricFactory, THREAD_STATE startThreads) { + public RemoteDelivery(DNSService dnsServer, DomainList domainList, MailQueueFactory queueFactory, MetricFactory metricFactory, ThreadState startThreads) { this.dnsServer = dnsServer; this.domainList = domainList; this.queueFactory = queueFactory; @@ -164,7 +164,7 @@ public class RemoteDelivery extends GenericMailet { } catch (UnknownHostException e) { LOGGER.error("Invalid bind setting ({}): ", configuration.getBindAddress(), e); } - if (startThreads == THREAD_STATE.START_THREADS) { + if (startThreads == ThreadState.START_THREADS) { initDeliveryThreads(); } } @@ -256,7 +256,7 @@ public class RemoteDelivery extends GenericMailet { */ @Override public synchronized void destroy() { - if (startThreads == THREAD_STATE.START_THREADS) { + if (startThreads == ThreadState.START_THREADS) { isDestroyed.set(true); executor.shutdown(); notifyAll(); http://git-wip-us.apache.org/repos/asf/james-project/blob/52c18ef6/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/jsieve/RejectAction.java ---------------------------------------------------------------------- diff --git a/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/jsieve/RejectAction.java b/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/jsieve/RejectAction.java index 9087d3e..473221b 100644 --- a/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/jsieve/RejectAction.java +++ b/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/jsieve/RejectAction.java @@ -86,35 +86,35 @@ public class RejectAction implements MailAction { humanText.append("\r\n"); humanText.append(anAction.getMessage()); - String reporting_UA_name = null; + String reportingUAName = null; try { - reporting_UA_name = InetAddress.getLocalHost() + reportingUAName = InetAddress.getLocalHost() .getCanonicalHostName(); } catch (UnknownHostException ex) { - reporting_UA_name = "localhost"; + reportingUAName = "localhost"; } - String reporting_UA_product = context.getServerInfo(); + String reportingUAProduct = context.getServerInfo(); String[] originalRecipients = aMail.getMessage().getHeader( "Original-Recipient"); - String original_recipient = null; + String originalRecipient = null; if (null != originalRecipients && originalRecipients.length > 0) { - original_recipient = originalRecipients[0]; + originalRecipient = originalRecipients[0]; } MailAddress soleRecipient = ActionUtils.getSoleRecipient(aMail); - String final_recipient = soleRecipient.asString(); - String original_message_id = aMail.getMessage().getMessageID(); + String finalRecipient = soleRecipient.asString(); + String originalMessageId = aMail.getMessage().getMessageID(); Multipart multipart = MDN.builder() .humanReadableText(humanText.toString()) .report( MDNReport.builder() - .reportingUserAgentField(reporting_UA_name, reporting_UA_product) - .finalRecipientField(final_recipient) - .originalRecipientField(original_recipient) - .originalMessageIdField(original_message_id) + .reportingUserAgentField(reportingUAName, reportingUAProduct) + .finalRecipientField(finalRecipient) + .originalRecipientField(originalRecipient) + .originalMessageIdField(originalMessageId) .dispositionField(Disposition.builder() .actionMode(DispositionActionMode.Automatic) .sendingMode(DispositionSendingMode.Automatic) http://git-wip-us.apache.org/repos/asf/james-project/blob/52c18ef6/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/remote/delivery/AddressesArrayToMailAddressListConverter.java ---------------------------------------------------------------------- diff --git a/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/remote/delivery/AddressesArrayToMailAddressListConverter.java b/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/remote/delivery/AddressesArrayToMailAddressListConverter.java new file mode 100644 index 0000000..7b10a18 --- /dev/null +++ b/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/remote/delivery/AddressesArrayToMailAddressListConverter.java @@ -0,0 +1,60 @@ +/**************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one * + * or more contributor license agreements. See the NOTICE file * + * distributed with this work for additional information * + * regarding copyright ownership. The ASF licenses this file * + * to you under the Apache License, Version 2.0 (the * + * "License"); you may not use this file except in compliance * + * with the License. You may obtain a copy of the License at * + * * + * http://www.apache.org/licenses/LICENSE-2.0 * + * * + * Unless required by applicable law or agreed to in writing, * + * software distributed under the License is distributed on an * + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * + * KIND, either express or implied. See the License for the * + * specific language governing permissions and limitations * + * under the License. * + ****************************************************************/ + +package org.apache.james.transport.mailets.remote.delivery; + +import java.util.Arrays; +import java.util.List; +import java.util.Optional; + +import javax.mail.Address; +import javax.mail.internet.AddressException; + +import org.apache.james.core.MailAddress; +import org.apache.james.util.OptionalUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.github.steveash.guavate.Guavate; +import com.google.common.collect.ImmutableList; + +public class AddressesArrayToMailAddressListConverter { + private static final Logger LOGGER = LoggerFactory.getLogger(AddressesArrayToMailAddressListConverter.class); + + public static List<MailAddress> getAddressesAsMailAddress(Address[] addresses) { + if (addresses == null) { + return ImmutableList.of(); + } + return Arrays.asList(addresses) + .stream() + .map(address -> toMailAddress(address)) + .flatMap(OptionalUtils::toStream) + .collect(Guavate.toImmutableList()); + } + + private static Optional<MailAddress> toMailAddress(Address address) { + try { + return Optional.of(new MailAddress(address.toString())); + } catch (AddressException e) { + LOGGER.debug("Can't parse unsent address {}", address, e); + return Optional.empty(); + } + } + +} http://git-wip-us.apache.org/repos/asf/james-project/blob/52c18ef6/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/remote/delivery/Bouncer.java ---------------------------------------------------------------------- diff --git a/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/remote/delivery/Bouncer.java b/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/remote/delivery/Bouncer.java new file mode 100644 index 0000000..0cff3cb --- /dev/null +++ b/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/remote/delivery/Bouncer.java @@ -0,0 +1,146 @@ +/**************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one * + * or more contributor license agreements. See the NOTICE file * + * distributed with this work for additional information * + * regarding copyright ownership. The ASF licenses this file * + * to you under the Apache License, Version 2.0 (the * + * "License"); you may not use this file except in compliance * + * with the License. You may obtain a copy of the License at * + * * + * http://www.apache.org/licenses/LICENSE-2.0 * + * * + * Unless required by applicable law or agreed to in writing, * + * software distributed under the License is distributed on an * + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * + * KIND, either express or implied. See the License for the * + * specific language governing permissions and limitations * + * under the License. * + ****************************************************************/ + +package org.apache.james.transport.mailets.remote.delivery; + +import java.io.PrintWriter; +import java.io.StringWriter; +import java.net.ConnectException; +import java.net.SocketException; +import java.net.UnknownHostException; + +import javax.mail.MessagingException; +import javax.mail.SendFailedException; + +import org.apache.james.core.MailAddress; +import org.apache.mailet.Mail; +import org.apache.mailet.MailetContext; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class Bouncer { + private static final Logger LOGGER = LoggerFactory.getLogger(Bouncer.class); + + public static final String DELIVERY_ERROR = "delivery-error"; + private final RemoteDeliveryConfiguration configuration; + private final MailetContext mailetContext; + + public Bouncer(RemoteDeliveryConfiguration configuration, MailetContext mailetContext) { + this.configuration = configuration; + this.mailetContext = mailetContext; + } + + public void bounce(Mail mail, Exception ex) { + if (mail.getSender() == null) { + LOGGER.debug("Null Sender: no bounce will be generated for {}", mail.getName()); + } else { + if (configuration.getBounceProcessor() != null) { + mail.setAttribute(DELIVERY_ERROR, getErrorMsg(ex)); + try { + mailetContext.sendMail(mail, configuration.getBounceProcessor()); + } catch (MessagingException e) { + LOGGER.warn("Exception re-inserting failed mail: ", e); + } + } else { + bounceWithMailetContext(mail, ex); + } + } + } + + + private void bounceWithMailetContext(Mail mail, Exception ex) { + LOGGER.debug("Sending failure message {}", mail.getName()); + try { + mailetContext.bounce(mail, explanationText(mail, ex)); + } catch (MessagingException me) { + LOGGER.warn("Encountered unexpected messaging exception while bouncing message", me); + } catch (Exception e) { + LOGGER.warn("Encountered unexpected exception while bouncing message", e); + } + } + + public String explanationText(Mail mail, Exception ex) { + StringWriter sout = new StringWriter(); + PrintWriter out = new PrintWriter(sout, true); + out.println("Hi. This is the James mail server at " + resolveMachineName() + "."); + out.println("I'm afraid I wasn't able to deliver your message to the following addresses."); + out.println("This is a permanent error; I've given up. Sorry it didn't work out. Below"); + out.println("I include the list of recipients and the reason why I was unable to deliver"); + out.println("your message."); + out.println(); + for (MailAddress mailAddress : mail.getRecipients()) { + out.println(mailAddress); + } + if (ex instanceof MessagingException) { + if (((MessagingException) ex).getNextException() == null) { + out.println(sanitizeExceptionMessage(ex)); + } else { + Exception ex1 = ((MessagingException) ex).getNextException(); + if (ex1 instanceof SendFailedException) { + out.println("Remote mail server told me: " + sanitizeExceptionMessage(ex1)); + } else if (ex1 instanceof UnknownHostException) { + out.println("Unknown host: " + sanitizeExceptionMessage(ex1)); + out.println("This could be a DNS server error, a typo, or a problem with the recipient's mail server."); + } else if (ex1 instanceof ConnectException) { + // Already formatted as "Connection timed out: connect" + out.println(sanitizeExceptionMessage(ex1)); + } else if (ex1 instanceof SocketException) { + out.println("Socket exception: " + sanitizeExceptionMessage(ex1)); + } else { + out.println(sanitizeExceptionMessage(ex1)); + } + } + } + out.println(); + return sout.toString(); + } + + private String sanitizeExceptionMessage(Exception e) { + if (e.getMessage() == null) { + return "null"; + } else { + return e.getMessage().trim(); + } + } + + private String resolveMachineName() { + try { + return configuration.getHeloNameProvider().getHeloName(); + } catch (Exception e) { + return "[address unknown]"; + } + } + + public String getErrorMsg(Exception ex) { + if (ex instanceof MessagingException) { + return getNestedExceptionMessage((MessagingException) ex); + } else { + return sanitizeExceptionMessage(ex); + } + } + + public String getNestedExceptionMessage(MessagingException me) { + if (me.getNextException() == null) { + return sanitizeExceptionMessage(me); + } else { + Exception ex1 = me.getNextException(); + return sanitizeExceptionMessage(ex1); + } + } +} http://git-wip-us.apache.org/repos/asf/james-project/blob/52c18ef6/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/remote/delivery/Converter7Bit.java ---------------------------------------------------------------------- diff --git a/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/remote/delivery/Converter7Bit.java b/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/remote/delivery/Converter7Bit.java new file mode 100644 index 0000000..63b17f6 --- /dev/null +++ b/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/remote/delivery/Converter7Bit.java @@ -0,0 +1,65 @@ +/**************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one * + * or more contributor license agreements. See the NOTICE file * + * distributed with this work for additional information * + * regarding copyright ownership. The ASF licenses this file * + * to you under the Apache License, Version 2.0 (the * + * "License"); you may not use this file except in compliance * + * with the License. You may obtain a copy of the License at * + * * + * http://www.apache.org/licenses/LICENSE-2.0 * + * * + * Unless required by applicable law or agreed to in writing, * + * software distributed under the License is distributed on an * + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * + * KIND, either express or implied. See the License for the * + * specific language governing permissions and limitations * + * under the License. * + ****************************************************************/ + +package org.apache.james.transport.mailets.remote.delivery; + +import java.io.IOException; + +import javax.mail.MessagingException; +import javax.mail.internet.MimeMultipart; +import javax.mail.internet.MimePart; + +import org.apache.mailet.MailetContext; + +public class Converter7Bit { + + private final MailetContext mailetContext; + + public Converter7Bit(MailetContext mailetContext) { + this.mailetContext = mailetContext; + } + + public MimePart convertTo7Bit(MimePart part) throws MessagingException, IOException { + if (part.isMimeType("multipart/*")) { + MimeMultipart parts = (MimeMultipart) part.getContent(); + int count = parts.getCount(); + for (int i = 0; i < count; i++) { + convertTo7Bit((MimePart) parts.getBodyPart(i)); + } + } else if ("8bit".equals(part.getEncoding())) { + // The content may already be in encoded the form (likely with mail + // created from a + // stream). In that case, just changing the encoding to + // quoted-printable will mangle + // the result when this is transmitted. We must first convert the + // content into its + // native format, set it back, and only THEN set the transfer + // encoding to force the + // content to be encoded appropriately. + + // if the part doesn't contain text it will be base64 encoded. + String contentTransferEncoding = part.isMimeType("text/*") ? "quoted-printable" : "base64"; + part.setContent(part.getContent(), part.getContentType()); + part.setHeader("Content-Transfer-Encoding", contentTransferEncoding); + part.addHeader("X-MIME-Autoconverted", "from 8bit to " + contentTransferEncoding + " by " + mailetContext.getServerInfo()); + } + return part; + } + +} http://git-wip-us.apache.org/repos/asf/james-project/blob/52c18ef6/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/remote/delivery/Delay.java ---------------------------------------------------------------------- diff --git a/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/remote/delivery/Delay.java b/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/remote/delivery/Delay.java new file mode 100644 index 0000000..af50fdd --- /dev/null +++ b/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/remote/delivery/Delay.java @@ -0,0 +1,112 @@ +/**************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one * + * or more contributor license agreements. See the NOTICE file * + * distributed with this work for additional information * + * regarding copyright ownership. The ASF licenses this file * + * to you under the Apache License, Version 2.0 (the * + * "License"); you may not use this file except in compliance * + * with the License. You may obtain a copy of the License at * + * * + * http://www.apache.org/licenses/LICENSE-2.0 * + * * + * Unless required by applicable law or agreed to in writing, * + * software distributed under the License is distributed on an * + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * + * KIND, either express or implied. See the License for the * + * specific language governing permissions and limitations * + * under the License. * + ****************************************************************/ + +package org.apache.james.transport.mailets.remote.delivery; + +import java.util.List; +import java.util.concurrent.TimeUnit; + +import javax.mail.MessagingException; + +import org.apache.james.util.TimeConverter; + +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.MoreObjects; +import com.google.common.base.Objects; +import com.google.common.base.Splitter; +import com.google.common.base.Strings; + +public class Delay { + /** + * <p> The optional attempt is the number of tries this delay should be used (default = 1). + * The delayTime is parsed by {@link TimeConverter}</p> + * + * @param initString the string to initialize this Delay object from. It has the form "[attempt\*]delaytime[unit]" + */ + public static Delay from(String initString) throws MessagingException { + if (Strings.isNullOrEmpty(initString)) { + throw new NumberFormatException("Null or Empty strings are not permitted"); + } + List<String> parts = Splitter.on('*').trimResults().splitToList(initString); + + if (parts.size() == 1) { + return new Delay(DEFAULT_ATTEMPTS, TimeConverter.getMilliSeconds(parts.get(0))); + } + if (parts.size() == 2) { + int attempts = Integer.parseInt(parts.get(0)); + if (attempts < 0) { + throw new MessagingException("Number of attempts negative in " + initString); + } + return new Delay(attempts, TimeConverter.getMilliSeconds(parts.get(1))); + } + throw new MessagingException(initString + " contains too much parts"); + } + + public static final long DEFAULT_DELAY_TIME = TimeUnit.HOURS.toMillis(6); + public static final int DEFAULT_ATTEMPTS = 1; + + private final int attempts; + private final long delayTimeInMs; + + public Delay() { + this(DEFAULT_ATTEMPTS, DEFAULT_DELAY_TIME); + } + + @VisibleForTesting + Delay(int attempts, long delayTime) { + this.attempts = attempts; + this.delayTimeInMs = delayTime; + } + + public long getDelayTimeInMs() { + return delayTimeInMs; + } + + public int getAttempts() { + return attempts; + } + + public List<Long> getExpendendDelays() { + return Repeat.repeat(delayTimeInMs, attempts); + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(this) + .add("attempts", attempts) + .add("delayTime", delayTimeInMs) + .toString(); + } + + @Override + public boolean equals(Object o) { + if (o instanceof Delay) { + Delay that = (Delay) o; + + return Objects.equal(this.attempts, that.attempts) + && Objects.equal(this.delayTimeInMs, that.delayTimeInMs); + } + return false; + } + + @Override + public int hashCode() { + return Objects.hashCode(attempts, delayTimeInMs); + } +} http://git-wip-us.apache.org/repos/asf/james-project/blob/52c18ef6/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/remote/delivery/DelaysAndMaxRetry.java ---------------------------------------------------------------------- diff --git a/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/remote/delivery/DelaysAndMaxRetry.java b/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/remote/delivery/DelaysAndMaxRetry.java new file mode 100644 index 0000000..7936f3d --- /dev/null +++ b/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/remote/delivery/DelaysAndMaxRetry.java @@ -0,0 +1,160 @@ +/**************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one * + * or more contributor license agreements. See the NOTICE file * + * distributed with this work for additional information * + * regarding copyright ownership. The ASF licenses this file * + * to you under the Apache License, Version 2.0 (the * + * "License"); you may not use this file except in compliance * + * with the License. You may obtain a copy of the License at * + * * + * http://www.apache.org/licenses/LICENSE-2.0 * + * * + * Unless required by applicable law or agreed to in writing, * + * software distributed under the License is distributed on an * + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * + * KIND, either express or implied. See the License for the * + * specific language governing permissions and limitations * + * under the License. * + ****************************************************************/ + +package org.apache.james.transport.mailets.remote.delivery; + +import java.util.List; + +import javax.mail.MessagingException; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Objects; +import com.google.common.base.Splitter; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.Iterables; + +public class DelaysAndMaxRetry { + + private static final Logger LOGGER = LoggerFactory.getLogger(DelaysAndMaxRetry.class); + + public static DelaysAndMaxRetry defaults() { + return new DelaysAndMaxRetry(RemoteDeliveryConfiguration.DEFAULT_MAX_RETRY, Repeat.repeat(new Delay(), RemoteDeliveryConfiguration.DEFAULT_MAX_RETRY)); + } + + public static DelaysAndMaxRetry from(int intendedMaxRetries, String delaysAsString) throws MessagingException { + List<Delay> delayTimesList = createDelayList(delaysAsString); + int totalAttempts = computeTotalAttempts(delayTimesList); + return getDelaysAndMaxRetry(intendedMaxRetries, totalAttempts, delayTimesList); + } + + private static DelaysAndMaxRetry getDelaysAndMaxRetry(int intendedMaxRetries, int totalAttempts, List<Delay> delayTimesList) throws MessagingException { + if (totalAttempts > intendedMaxRetries) { + LOGGER.warn("Total number of delayTime attempts exceeds maxRetries specified. Increasing maxRetries from {} to {}", intendedMaxRetries, totalAttempts); + return new DelaysAndMaxRetry(totalAttempts, delayTimesList); + } else { + int extra = intendedMaxRetries - totalAttempts; + if (extra > 0) { + LOGGER.warn("maxRetries is larger than total number of attempts specified. Increasing last delayTime with {} attempts ", extra); + return addExtraAttemptToLastDelay(intendedMaxRetries, extra, delayTimesList); + } + return new DelaysAndMaxRetry(intendedMaxRetries, delayTimesList); + } + } + + private static DelaysAndMaxRetry addExtraAttemptToLastDelay(int intendedMaxRetries, int extra, List<Delay> delayTimesList) throws MessagingException { + if (delayTimesList.size() != 0) { + Delay lastDelay = delayTimesList.get(delayTimesList.size() - 1); + LOGGER.warn("Delay of {} msecs is now attempted: {} times", lastDelay.getDelayTimeInMs(), lastDelay.getAttempts()); + return new DelaysAndMaxRetry(intendedMaxRetries, + ImmutableList.copyOf( + Iterables.concat( + Iterables.limit(delayTimesList, delayTimesList.size() - 1), + ImmutableList.of(new Delay(lastDelay.getAttempts() + extra, lastDelay.getDelayTimeInMs()))))); + } else { + throw new MessagingException("No delaytimes, cannot continue"); + } + } + + private static List<Delay> createDelayList(String delaysAsString) { + if (delaysAsString == null) { + // Use default delayTime. + return ImmutableList.of(new Delay()); + } + + List<String> delayStrings = Splitter.on(',') + .omitEmptyStrings() + .trimResults() + .splitToList(delaysAsString); + + ImmutableList.Builder<Delay> builder = ImmutableList.builder(); + try { + for (String s : delayStrings) { + builder.add(Delay.from(s)); + } + return builder.build(); + } catch (Exception e) { + LOGGER.warn("Invalid delayTime setting: {}", delaysAsString); + return builder.build(); + } + } + + private static int computeTotalAttempts(List<Delay> delayList) { + return delayList.stream() + .mapToInt(Delay::getAttempts) + .sum(); + } + + private final int maxRetries; + private final List<Delay> delays; + + @VisibleForTesting + DelaysAndMaxRetry(int maxRetries, List<Delay> delays) { + this.maxRetries = maxRetries; + this.delays = ImmutableList.copyOf(delays); + } + + public int getMaxRetries() { + return maxRetries; + } + + /** + * <p> + * This method expands an ArrayList containing Delay objects into an array + * holding the only delaytime in the order. + * </p> + * <p/> + * So if the list has 2 Delay objects the first having attempts=2 and + * delaytime 4000 the second having attempts=1 and delaytime=300000 will be + * expanded into this array: + * <p/> + * <pre> + * long[0] = 4000 + * long[1] = 4000 + * long[2] = 300000 + * </pre> + * + * @param list the list to expand + * @return the expanded list + */ + public List<Long> getExpandedDelays() { + ImmutableList.Builder<Long> builder = ImmutableList.builder(); + for (Delay delay: delays) { + builder.addAll(delay.getExpendendDelays()); + } + return builder.build(); + } + + @Override + public boolean equals(Object o) { + if (o instanceof DelaysAndMaxRetry) { + DelaysAndMaxRetry that = (DelaysAndMaxRetry) o; + return Objects.equal(this.maxRetries, that.maxRetries) + && Objects.equal(this.delays, that.delays); + } + return false; + } + + @Override + public int hashCode() { + return Objects.hashCode(maxRetries, delays); + } +} http://git-wip-us.apache.org/repos/asf/james-project/blob/52c18ef6/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/remote/delivery/DeliveryRetriesHelper.java ---------------------------------------------------------------------- diff --git a/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/remote/delivery/DeliveryRetriesHelper.java b/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/remote/delivery/DeliveryRetriesHelper.java new file mode 100644 index 0000000..08071e5 --- /dev/null +++ b/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/remote/delivery/DeliveryRetriesHelper.java @@ -0,0 +1,50 @@ +/**************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one * + * or more contributor license agreements. See the NOTICE file * + * distributed with this work for additional information * + * regarding copyright ownership. The ASF licenses this file * + * to you under the Apache License, Version 2.0 (the * + * "License"); you may not use this file except in compliance * + * with the License. You may obtain a copy of the License at * + * * + * http://www.apache.org/licenses/LICENSE-2.0 * + * * + * Unless required by applicable law or agreed to in writing, * + * software distributed under the License is distributed on an * + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * + * KIND, either express or implied. See the License for the * + * specific language governing permissions and limitations * + * under the License. * + ****************************************************************/ + +package org.apache.james.transport.mailets.remote.delivery; + +import java.io.Serializable; + +import org.apache.mailet.Mail; + +public class DeliveryRetriesHelper { + + public static final String DELIVERY_RETRY_COUNT = "delivery_retry_count"; + + public static int retrieveRetries(Mail mail) { + try { + Serializable value = mail.getAttribute(DELIVERY_RETRY_COUNT); + if (value != null) { + return (Integer) value; + } + return 0; + } catch (ClassCastException e) { + return 0; + } + } + + public static void initRetries(Mail mail) { + mail.setAttribute(DELIVERY_RETRY_COUNT, 0); + } + + public static void incrementRetries(Mail mail) { + mail.setAttribute(DELIVERY_RETRY_COUNT, retrieveRetries(mail) + 1); + } + +} http://git-wip-us.apache.org/repos/asf/james-project/blob/52c18ef6/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/remote/delivery/DeliveryRunnable.java ---------------------------------------------------------------------- diff --git a/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/remote/delivery/DeliveryRunnable.java b/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/remote/delivery/DeliveryRunnable.java new file mode 100644 index 0000000..53b0420 --- /dev/null +++ b/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/remote/delivery/DeliveryRunnable.java @@ -0,0 +1,181 @@ +/**************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one * + * or more contributor license agreements. See the NOTICE file * + * distributed with this work for additional information * + * regarding copyright ownership. The ASF licenses this file * + * to you under the Apache License, Version 2.0 (the * + * "License"); you may not use this file except in compliance * + * with the License. You may obtain a copy of the License at * + * * + * http://www.apache.org/licenses/LICENSE-2.0 * + * * + * Unless required by applicable law or agreed to in writing, * + * software distributed under the License is distributed on an * + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * + * KIND, either express or implied. See the License for the * + * specific language governing permissions and limitations * + * under the License. * + ****************************************************************/ + +package org.apache.james.transport.mailets.remote.delivery; + +import java.util.Date; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.function.Supplier; + +import org.apache.james.dnsservice.api.DNSService; +import org.apache.james.lifecycle.api.LifecycleUtil; +import org.apache.james.metrics.api.Metric; +import org.apache.james.metrics.api.MetricFactory; +import org.apache.james.metrics.api.TimeMetric; +import org.apache.james.queue.api.MailPrioritySupport; +import org.apache.james.queue.api.MailQueue; +import org.apache.mailet.Mail; +import org.apache.mailet.MailetContext; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.annotations.VisibleForTesting; + +public class DeliveryRunnable implements Runnable { + private static final Logger LOGGER = LoggerFactory.getLogger(DeliveryRunnable.class); + + public static final Supplier<Date> CURRENT_DATE_SUPPLIER = Date::new; + public static final AtomicBoolean DEFAULT_NOT_STARTED = new AtomicBoolean(false); + private static final String OUTGOING_MAILS = "outgoingMails"; + public static final String REMOTE_DELIVERY_TRIAL = "RemoteDeliveryTrial"; + + private final MailQueue queue; + private final RemoteDeliveryConfiguration configuration; + private final Metric outgoingMailsMetric; + private final MetricFactory metricFactory; + private final Bouncer bouncer; + private final MailDelivrer mailDelivrer; + private final AtomicBoolean isDestroyed; + private final Supplier<Date> dateSupplier; + + public DeliveryRunnable(MailQueue queue, RemoteDeliveryConfiguration configuration, DNSService dnsServer, MetricFactory metricFactory, + MailetContext mailetContext, Bouncer bouncer, AtomicBoolean isDestroyed) { + this(queue, configuration, metricFactory, bouncer, + new MailDelivrer(configuration, new MailDelivrerToHost(configuration, mailetContext), dnsServer, bouncer), + isDestroyed, CURRENT_DATE_SUPPLIER); + } + + @VisibleForTesting + DeliveryRunnable(MailQueue queue, RemoteDeliveryConfiguration configuration, MetricFactory metricFactory, Bouncer bouncer, + MailDelivrer mailDelivrer, AtomicBoolean isDestroyeds, Supplier<Date> dateSupplier) { + this.queue = queue; + this.configuration = configuration; + this.outgoingMailsMetric = metricFactory.generate(OUTGOING_MAILS); + this.bouncer = bouncer; + this.mailDelivrer = mailDelivrer; + this.isDestroyed = isDestroyeds; + this.dateSupplier = dateSupplier; + this.metricFactory = metricFactory; + } + + @Override + public void run() { + try { + while (!Thread.interrupted() && !isDestroyed.get()) { + runStep(); + } + } finally { + // Restore the thread state to non-interrupted. + Thread.interrupted(); + } + } + + private void runStep() { + TimeMetric timeMetric = null; + try { + // Get the 'mail' object that is ready for deliverying. If no message is + // ready, the 'accept' will block until message is ready. + // The amount of time to block is determined by the 'getWaitTime' method of the MultipleDelayFilter. + MailQueue.MailQueueItem queueItem = queue.deQueue(); + timeMetric = metricFactory.timer(REMOTE_DELIVERY_TRIAL); + Mail mail = queueItem.getMail(); + + try { + if (configuration.isDebug()) { + LOGGER.debug("{} will process mail {}", Thread.currentThread().getName(), mail.getName()); + } + attemptDelivery(mail); + LifecycleUtil.dispose(mail); + mail = null; + queueItem.done(true); + } catch (Exception e) { + // Prevent unexpected exceptions from causing looping by removing message from outgoing. + // DO NOT CHANGE THIS to catch Error! + // For example, if there were an OutOfMemory condition caused because + // something else in the server was abusing memory, we would not want to start purging the retrying spool! + LOGGER.error("Exception caught in RemoteDelivery.run()", e); + LifecycleUtil.dispose(mail); + queueItem.done(false); + } + + } catch (Throwable e) { + if (!isDestroyed.get()) { + LOGGER.error("Exception caught in RemoteDelivery.run()", e); + } + } finally { + if (timeMetric != null) { + timeMetric.stopAndPublish(); + } + } + } + + @VisibleForTesting + void attemptDelivery(Mail mail) throws MailQueue.MailQueueException { + ExecutionResult executionResult = mailDelivrer.deliver(mail); + switch (executionResult.getExecutionState()) { + case SUCCESS: + outgoingMailsMetric.increment(); + break; + case TEMPORARY_FAILURE: + handleTemporaryFailure(mail, executionResult); + break; + case PERMANENT_FAILURE: + bouncer.bounce(mail, executionResult.getException().orElse(null)); + break; + } + } + + private void handleTemporaryFailure(Mail mail, ExecutionResult executionResult) throws MailQueue.MailQueueException { + if (!mail.getState().equals(Mail.ERROR)) { + mail.setState(Mail.ERROR); + DeliveryRetriesHelper.initRetries(mail); + mail.setLastUpdated(dateSupplier.get()); + } + int retries = DeliveryRetriesHelper.retrieveRetries(mail); + + if (retries < configuration.getMaxRetries()) { + reAttemptDelivery(mail, retries); + } else { + LOGGER.debug("Bouncing message {} after {} retries", mail.getName(), retries); + bouncer.bounce(mail, new Exception("Too many retries failure. Bouncing after " + retries + " retries.", executionResult.getException().orElse(null))); + } + } + + private void reAttemptDelivery(Mail mail, int retries) throws MailQueue.MailQueueException { + LOGGER.debug("Storing message {} into outgoing after {} retries", mail.getName(), retries); + DeliveryRetriesHelper.incrementRetries(mail); + mail.setLastUpdated(dateSupplier.get()); + // Something happened that will delay delivery. Store it back in the retry repository. + long delay = getNextDelay(DeliveryRetriesHelper.retrieveRetries(mail)); + + if (configuration.isUsePriority()) { + // Use lowest priority for retries. See JAMES-1311 + mail.setAttribute(MailPrioritySupport.MAIL_PRIORITY, MailPrioritySupport.LOW_PRIORITY); + } + queue.enQueue(mail, delay, TimeUnit.MILLISECONDS); + } + + private long getNextDelay(int retry_count) { + if (retry_count > configuration.getDelayTimes().size()) { + return Delay.DEFAULT_DELAY_TIME; + } + return configuration.getDelayTimes().get(retry_count - 1); + } +} --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
