I need a pure Apache Commons VFS solution/code/example for
Uploading a local file to Remote Host Location
Check if a File exists in Remote Host Location
Downloading a Remote Host File to Local file location
Move a file from one Remote Location to another in the same Host
Delete a file from the Remote Host Location
via SFTP calls.
The solution should only use Apache Commons VFS api and shouldn't refer to the underlying JSCH library.
The below SFTP Utility gives an example of Upload, Exist, Download, Move and Delete operations. I have used this in several of my projects. The below code uses api calls from Apache Commons VFS library only.
Please make sure that you put the following JAR's in your project's build path:
commons-logging-1.1.3.jar
commons-vfs2-2.0.jar
hamcrest-core-1.3.jar
jsch-0.1.50.jar
Any other compatible versions would do as well.
import java.io.File;
import org.apache.commons.vfs2.FileObject;
import org.apache.commons.vfs2.FileSystemException;
import org.apache.commons.vfs2.FileSystemOptions;
import org.apache.commons.vfs2.Selectors;
import org.apache.commons.vfs2.impl.StandardFileSystemManager;
import org.apache.commons.vfs2.provider.sftp.SftpFileSystemConfigBuilder;
/**
* The class SFTPUtil containing uploading, downloading, checking if file exists
* and deleting functionality using Apache Commons VFS (Virtual File System)
* Library
*
* #author Ashok
*
*/
public class SFTPUtility {
public static void main(String[] args) {
String hostName = "PutYourHostNameHere";
String username = "PutYourUserNameForHostHere";
String password = "PutYourPasswordForHostHere";
String localFilePath = "C:\\FakePath\\FakeFile.txt";
String remoteFilePath = "/FakeRemotePath/FakeRemoteFile.txt";
String remoteTempFilePath = "/FakeRemoteTempPath/FakeRemoteTempFile.txt";
upload(hostName, username, password, localFilePath, remoteFilePath);
exist(hostName, username, password, remoteFilePath);
download(hostName, username, password, localFilePath,remoteFilePath);
move(hostName, username, password, remoteFilePath, remoteTempFilePath);
delete(hostName, username, password, remoteFilePath);
}
/**
* Method to upload a file in Remote server
*
* #param hostName
* HostName of the server
* #param username
* UserName to login
* #param password
* Password to login
* #param localFilePath
* LocalFilePath. Should contain the entire local file path -
* Directory and Filename with \\ as separator
* #param remoteFilePath
* remoteFilePath. Should contain the entire remote file path -
* Directory and Filename with / as separator
*/
public static void upload(String hostName, String username, String password, String localFilePath, String remoteFilePath) {
File file = new File(localFilePath);
if (!file.exists())
throw new RuntimeException("Error. Local file not found");
StandardFileSystemManager manager = new StandardFileSystemManager();
try {
manager.init();
// Create local file object
FileObject localFile = manager.resolveFile(file.getAbsolutePath());
// Create remote file object
FileObject remoteFile = manager.resolveFile(createConnectionString(hostName, username, password, remoteFilePath), createDefaultOptions());
/*
* use createDefaultOptions() in place of fsOptions for all default
* options - Ashok.
*/
// Copy local file to sftp server
remoteFile.copyFrom(localFile, Selectors.SELECT_SELF);
System.out.println("File upload success");
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
manager.close();
}
}
public static boolean move(String hostName, String username, String password, String remoteSrcFilePath, String remoteDestFilePath){
StandardFileSystemManager manager = new StandardFileSystemManager();
try {
manager.init();
// Create remote object
FileObject remoteFile = manager.resolveFile(createConnectionString(hostName, username, password, remoteSrcFilePath), createDefaultOptions());
FileObject remoteDestFile = manager.resolveFile(createConnectionString(hostName, username, password, remoteDestFilePath), createDefaultOptions());
if (remoteFile.exists()) {
remoteFile.moveTo(remoteDestFile);;
System.out.println("Move remote file success");
return true;
}
else{
System.out.println("Source file doesn't exist");
return false;
}
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
manager.close();
}
}
/**
* Method to download the file from remote server location
*
* #param hostName
* HostName of the server
* #param username
* UserName to login
* #param password
* Password to login
* #param localFilePath
* LocalFilePath. Should contain the entire local file path -
* Directory and Filename with \\ as separator
* #param remoteFilePath
* remoteFilePath. Should contain the entire remote file path -
* Directory and Filename with / as separator
*/
public static void download(String hostName, String username, String password, String localFilePath, String remoteFilePath) {
StandardFileSystemManager manager = new StandardFileSystemManager();
try {
manager.init();
// Append _downlaod_from_sftp to the given file name.
//String downloadFilePath = localFilePath.substring(0, localFilePath.lastIndexOf(".")) + "_downlaod_from_sftp" + localFilePath.substring(localFilePath.lastIndexOf("."), localFilePath.length());
// Create local file object. Change location if necessary for new downloadFilePath
FileObject localFile = manager.resolveFile(localFilePath);
// Create remote file object
FileObject remoteFile = manager.resolveFile(createConnectionString(hostName, username, password, remoteFilePath), createDefaultOptions());
// Copy local file to sftp server
localFile.copyFrom(remoteFile, Selectors.SELECT_SELF);
System.out.println("File download success");
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
manager.close();
}
}
/**
* Method to delete the specified file from the remote system
*
* #param hostName
* HostName of the server
* #param username
* UserName to login
* #param password
* Password to login
* #param localFilePath
* LocalFilePath. Should contain the entire local file path -
* Directory and Filename with \\ as separator
* #param remoteFilePath
* remoteFilePath. Should contain the entire remote file path -
* Directory and Filename with / as separator
*/
public static void delete(String hostName, String username, String password, String remoteFilePath) {
StandardFileSystemManager manager = new StandardFileSystemManager();
try {
manager.init();
// Create remote object
FileObject remoteFile = manager.resolveFile(createConnectionString(hostName, username, password, remoteFilePath), createDefaultOptions());
if (remoteFile.exists()) {
remoteFile.delete();
System.out.println("Delete remote file success");
}
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
manager.close();
}
}
// Check remote file is exist function:
/**
* Method to check if the remote file exists in the specified remote
* location
*
* #param hostName
* HostName of the server
* #param username
* UserName to login
* #param password
* Password to login
* #param remoteFilePath
* remoteFilePath. Should contain the entire remote file path -
* Directory and Filename with / as separator
* #return Returns if the file exists in the specified remote location
*/
public static boolean exist(String hostName, String username, String password, String remoteFilePath) {
StandardFileSystemManager manager = new StandardFileSystemManager();
try {
manager.init();
// Create remote object
FileObject remoteFile = manager.resolveFile(createConnectionString(hostName, username, password, remoteFilePath), createDefaultOptions());
System.out.println("File exist: " + remoteFile.exists());
return remoteFile.exists();
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
manager.close();
}
}
/**
* Generates SFTP URL connection String
*
* #param hostName
* HostName of the server
* #param username
* UserName to login
* #param password
* Password to login
* #param remoteFilePath
* remoteFilePath. Should contain the entire remote file path -
* Directory and Filename with / as separator
* #return concatenated SFTP URL string
*/
public static String createConnectionString(String hostName, String username, String password, String remoteFilePath) {
return "sftp://" + username + ":" + password + "#" + hostName + "/" + remoteFilePath;
}
/**
* Method to setup default SFTP config
*
* #return the FileSystemOptions object containing the specified
* configuration options
* #throws FileSystemException
*/
public static FileSystemOptions createDefaultOptions() throws FileSystemException {
// Create SFTP options
FileSystemOptions opts = new FileSystemOptions();
// SSH Key checking
SftpFileSystemConfigBuilder.getInstance().setStrictHostKeyChecking(opts, "no");
/*
* Using the following line will cause VFS to choose File System's Root
* as VFS's root. If I wanted to use User's home as VFS's root then set
* 2nd method parameter to "true"
*/
// Root directory set to user home
SftpFileSystemConfigBuilder.getInstance().setUserDirIsRoot(opts, false);
// Timeout is count by Milliseconds
SftpFileSystemConfigBuilder.getInstance().setTimeout(opts, 10000);
return opts;
}
}
Related
I have a piece of Java code (see below), which has not been changed in a while and worked two weeks ago. When I run it now, I suddenly get an "AUTHENTICATE FAILED." I get the error on two different PCs, and I have validated that the credentials used still work when I log into may office365 mailbox using the browser.
Has something changed on the office365 side I should know of?
The error I get is:
javax.mail.AuthenticationFailedException: AUTHENTICATE failed.
at com.sun.mail.imap.IMAPStore.protocolConnect(IMAPStore.java:732)
at javax.mail.Service.connect(Service.java:366)
at javax.mail.Service.connect(Service.java:246)
at my.application.input.imap.ImapMailBoxReader.processOnMessages(ImapMailBoxReader.java:69)
Digging deeper, the cause seems to be an A3 NO AUTHENTICATE failed. response (line 730 of javax.mail.IMAPStore).
The code I use is the following (using javax.mail version 1.6.2):
package my.application.input.imap;
import my.application.dao.PhysicalTransactionDao;
import com.sun.mail.util.MailSSLSocketFactory;
import javax.mail.*;
import javax.mail.search.AndTerm;
import javax.mail.search.ComparisonTerm;
import javax.mail.search.ReceivedDateTerm;
import javax.mail.search.SearchTerm;
import java.time.LocalDate;
import java.time.ZoneId;
import java.util.*;
import java.io.*;
import java.util.function.Consumer;
public class ImapMailBoxReader {
private String host;
private String username;
private String password;
public static void main(String[] args) {
ImapMailBoxReader imapReader = new ImapMailBoxReader(
"outlook.office365.com",
"myemail",
"mypassword");
LocalDate startDate = LocalDate.of(2022,4,1);
LocalDate endDate = LocalDate.of(2022,7,1);
imapReader.processOnMessages("Inbox", startDate, endDate, SomeClass::processMessage);
}
public ImapMailBoxReader(String host, String username, String password) {
this.host = host;
this.username = username;
this.password = password;
}
/**
* Returns all messages on or after the given since date, until today. If the given since date is null, all messages
* are returned
* #param folder the folder to search through
* #param since the given since date
* #param mailConsumer the consumer that will process the messages retrieved
*/
public void processOnMessages(String folder, LocalDate since, Consumer<Message> mailConsumer) {
processOnMessages(folder, since, null, mailConsumer);
}
/**
* Runs a given mailconsumer on all messages in the given imap folder that have been received on, or after, the given
* since date and before the given until date. If since is null, all messages are returned up to the until date.
* If until is null, all messages are returned from the since date until now. If both are null, all messages are
* returned.
* #param folder the folder to search through
* #param since if specified, only messages from this date on are returned
* #param mailconsumer the consumer that will be executed on the messages
*/
public void processOnMessages(String folder, LocalDate since, LocalDate until, Consumer<Message> mailconsumer) {
try {
Properties prop = new Properties();
MailSSLSocketFactory sf = new MailSSLSocketFactory();
sf.setTrustAllHosts(true);
prop.setProperty("mail.imap.starttls.enable", "true");
prop.put("mail.imap.starttls.enable", "true");
prop.put("mail.imap.ssl.socketFactory", sf);
//Connect to the server
Session session = Session.getDefaultInstance(prop, null);
Store store = session.getStore("imap");
store.connect(host, username, password);
//open the inbox folder
Folder inbox = store.getFolder(folder);
inbox.open(Folder.READ_ONLY);
Message[] messages;
if (since != null) {
Date startDate = Date.from(since.atStartOfDay(ZoneId.systemDefault()).toInstant());
SearchTerm newerThan = new ReceivedDateTerm(ComparisonTerm.GE, startDate);
if (until != null) {
Date endDate = Date.from(until.plusDays(1).atStartOfDay(ZoneId.systemDefault()).toInstant());
SearchTerm olderThan = new ReceivedDateTerm(ComparisonTerm.LT, endDate);
SearchTerm both = new AndTerm(olderThan, newerThan);
messages = inbox.search(both);
} else {
messages = inbox.search(newerThan);
}
} else if (until != null) {
Date endDate = Date.from(until.plusDays(1).atStartOfDay(ZoneId.systemDefault()).toInstant());
SearchTerm olderThan = new ReceivedDateTerm(ComparisonTerm.LT, endDate);
messages = inbox.search(olderThan);
} else {
messages = inbox.getMessages();
}
for (Message m: messages) {
mailconsumer.accept(m);
}
inbox.close(false);
store.close();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* Will search through all attachments of the message, and will pass those with the given extension (if provided)
* to the consumer. Note that the connection to the imap should be open for all this magic to work. this method
* is intended to be called from a messageconsumer during the processOnMessages method from this class.
* #param message the message for which the attachments are needed.
* #param extension if provided, only attachments with this extension will be provided
* #param attachmentConsumer the consumer that will process the attachments
* #throws IOException if for some reason the attachments can't be accessed
* #throws MessagingException for other messaging errors
*/
public static void processOnAttachments(Message message, String extension, Consumer<InputStream> attachmentConsumer)
throws IOException, MessagingException {
Multipart multipart = (Multipart) message.getContent();
for (int i = 0; i < multipart.getCount(); i++) {
BodyPart bodyPart = multipart.getBodyPart(i);
if (bodyPart.getFileName() != null && bodyPart.getFileName().endsWith(extension)) {
attachmentConsumer.accept(bodyPart.getInputStream());
}
}
}
}
Again, this code worked perfectly two weeks ago, nothing was changed on my side and the credentials still work...
All suggestions are appreciated.
You must use OAuth2, legacy security may have been deprecated.
Works with Thunderbird for example.
Just see how to reactivate legacy auth or use OAuth2 with your java client.
#see https://learn.microsoft.com/fr-fr/exchange/troubleshoot/administration/cannot-connect-mailbox-pop-imap-outlook to reactivate legacy
PS : To use shared mailbox, you must user mailbox name as user, and OAuth2 user + password and MFA if needed during Auth part, all that instead of old way (user#domain\sharedmailbox + password)
I have a class that downloads files from FTP servers using the Apache FTP Client, and I want to test it. For doing so, I decided to use the FakeFtpServer class from MockFtpServer, but it always fails with the same error: Connection refused (Connection refused).
My test class:
public class FTPConnectionTest {
/** Mock FTP Server */
private static FakeFtpServer FAKE_FTP_SERVER;
/** Mock FTP Server address */
private static String ADDRESS = "localhost";
/** Mock FTP server user name */
private static String USERNAME = "ftpuser";
/** Mock FTP Server password */
private static String PASSWORD = "ftppasswd";
/** Mock FTP Server default root */
private static String ROOT;
/** Mock FTP Server port */
private static int PORT = 0;
/** Test directory in the mock server */
private static String DIRECTORY = "/directory";
/** Test file 1*/
private static String FILE1 = "/Human_satellite.txt";
/** Content of test file 1 */
private static String FILE1_CONTENT = "Ground control to Major Tom...";
/** Test file 1*/
private static String FILE2 = "/wall-e.txt";
/** Content of test file 1 */
private static String FILE2_CONTENT = "If lost in space, use fire extinguisher";
/** Test file 1*/
private static String FILE3 = "/buzz_lightyear.txt";
/** Content of test file 1 */
private static String FILE3_CONTENT = "To infinity, and beyond !";
/**
* Set up a mock FTP server before running the tests
*/
#BeforeClass
public static void setupMock() {
// Create Mock server
FAKE_FTP_SERVER = new FakeFtpServer();
FAKE_FTP_SERVER.setServerControlPort(0); // Automatically finds available port
PORT = FAKE_FTP_SERVER.getServerControlPort();
FAKE_FTP_SERVER.addUserAccount(new UserAccount(USERNAME, PASSWORD, ROOT));
// Get the path to the resources folder where to run the mock FTP
File mockDir = new File("src/test/resources/ftp/mock");
ROOT = mockDir.getAbsolutePath();
// Create mock files
FileSystem fileSystem = new UnixFakeFileSystem();
fileSystem.add(new DirectoryEntry(ROOT));
fileSystem.add(new FileEntry(ROOT + FILE1, FILE1_CONTENT));
fileSystem.add(new DirectoryEntry(ROOT + DIRECTORY));
fileSystem.add(new FileEntry(ROOT + DIRECTORY + FILE2, FILE2_CONTENT));
fileSystem.add(new FileEntry(ROOT + DIRECTORY + FILE3, FILE3_CONTENT));
FAKE_FTP_SERVER.setFileSystem(fileSystem);
FAKE_FTP_SERVER.start();
}
/**
* The the mock FTP Server once the tests are done
*/
#AfterClass
public static void stop() {
FAKE_FTP_SERVER.stop();
}
/**
* Test
*/
#Test
public void testFetchNewFiles () {
// Get output path
String outputPath = "src/test/resources/ftp/result";
File output = new File(outputPath);
outputPath = output.getAbsolutePath();
// Create the connection and get the files
FTPConnection conn = new FTPConnection(ADDRESS, PORT, USERNAME, PASSWORD, outputPath);
conn.fetchNewFiles();
// Check that the files have bin downloaded
File file1 = new File(outputPath + FILE1);
assertTrue(file1.exists());
}
}
And here is the part of the FTP class that fails:
public class FTPConnection {
/** Logger */
private Logger logger;
/** The FTP Client used to connect to the server */
private FTPClient client;
/** The address of the server */
private String server;
/** The port of the server (default 21) */
private int port;
/** The user name to use to connect to the server */
private String user;
/** The password to use to connect to the server */
private String password;
/** The directory where to save the downloaded files */
private String output;
/**
* Constructor
* #param server the address of the FTP server
* #param port the port of the FTP server
* #param user the user name to use to connect to the server
* #param password the password to use to connect to the server
* #param output the output directory where to download the files
*/
public FTPConnection (String server, int port, String user, String password, String output) {
this.logger = LoggerFactory.getLogger(FTPConnection.class);
this.server = server;
this.port = port;
this.user = user;
this.password = password;
this.output = output;
this.client = new FTPClient();
}
/**
* Constructor
* #param server the address of the FTP server
* #param user the user name to use to connect to the server
* #param password the password to use to connect to the server
* #param output the output directory where to download the files
*/
public FTPConnection (String server, String user, String password, String output) {
this(server, 21, user, password, output);
}
public void fetchNewFiles() {
// Connect to the server
try {
this.client.connect(server, port); // That's the line that fails
this.client.login(user, password);
} catch (IOException e) {
logger.error("Error while connecting to FTP server '" + this.server + "': " + e.getMessage());
e.printStackTrace();
return;
}
}
}
And finally an extract of what's going on in the console:
19:24:31.417 [Thread-1] INFO org.mockftpserver.fake.FakeFtpServer - Starting the server on port 0
19:24:31.419 [Thread-1] INFO org.mockftpserver.fake.FakeFtpServer - Actual server port is 34003
19:24:31.444 [main] ERROR com.my.project.importHandler.FTPConnection - Error while connecting to FTP server 'localhost': Connection refused (Connection refused)
*** STACK TRACE ***
19:24:31.457 [Thread-1] DEBUG org.mockftpserver.fake.FakeFtpServer - Cleaning up server...
19:24:31.457 [Thread-1] INFO org.mockftpserver.fake.FakeFtpServer - Server stopped.
Ok, I found it: FAKE_FTP_SERVER.setServerControlPort(0); sets the value of the server port to 0, and the automatic selection of an available port only happens during FAKE_FTP_SERVER.start();. I moved the line PORT = FAKE_FTP_SERVER.getServerControlPort(); after FAKE_FTP_SERVER.start(); and now it works.
I can't seem to connect a database using c3p0 when I use:
DriverManager.getConnection("jdbc:mysql://localhost:3306/rdmssql", "root", "");
no exception is thrown.
However, when I try to connection using the c3p0 connection pool:
private ComboPooledDataSource connectionPool;
...other code
/**
*
* #return
* #throws Exception
*/
public Connection getConnection() throws Exception {
return getInstance().connectionPool.getConnection();
}
/**
*
* #param driver
* #param hostname
* #param databaseName
* #param username
* #param pwd
* #throws Exception
* #throws PropertyVetoException
*/
private void setConnectionDetails(String driver, String hostname, String databaseName, String username, String pwd) throws Exception, PropertyVetoException {
connectionPool.setDriverClass("com.mysql.jdbc.Driver");
connectionPool.setJdbcUrl(driver + "://" + hostname + "/" + databaseName);
connectionPool.setUser(username);
connectionPool.setPassword(pwd);
// the settings below are optional -- c3p0 can work with defaults
// will work on this in the future
connectionPool.setInitialPoolSize(5);
connectionPool.setMinPoolSize(5);
connectionPool.setAcquireIncrement(5);
connectionPool.setMaxPoolSize(20);
connectionPool.setMaxStatements(180);
}
an java.sql.SQLException: Access denied for user: 'root#127.0.0.1' (Using password: YES) is thrown. I'm not sure if I missed some configurations for my c3p0.
The exception says it ('using password': YES).
The driver manager version does not use a password (and succeeds), whereas the connection pool version DOES (and fails).
Check the argument value passed to pwd (and make it send "").
I tried copying a folder from network to a local system using apache VFS2. I added all dependency from maven given in their pom.xml. But still im getting this error "Caused by: org.apache.commons.vfs2.FileSystemException:
Expecting / to follow the hostname in URI "Caused by: org.apache.commons.vfs2.FileSystemException: Expecting / to follow the hostname in URI "sftp://user:*****#network/opt/file.txt"**
I searched SO site, stackexchange,superuser and found this issue topic, and remedy suggested was jar missing.
Somebody please throw some light on this issue and please provide me exact list of jars to be downloaded with intellij.
Im using this code.
import org.apache.commons.vfs2.FileObject;
import org.apache.commons.vfs2.FileSystemException;
import org.apache.commons.vfs2.FileSystemOptions;
import org.apache.commons.vfs2.Selectors;
import org.apache.commons.vfs2.impl.StandardFileSystemManager;
import org.apache.commons.vfs2.provider.sftp.SftpFileSystemConfigBuilder;
import java.io.File;
/**
* The class SFTPUtil containing uploading, downloading, checking if file exists
* and deleting functionality using Apache Commons VFS (Virtual File System)
* Library
*
* #author Ashok
*
*/
public class SFTPUtility {
public static void main(String[] args) {
String hostName = "10.2.55.66";
String username = "user";
String password = "password#network";
String localFilePath = "/opt/FakeFile.txt";
String remoteFilePath = "/opt/file.txt";
String remoteTempFilePath = "/tmp";
//upload(hostName, username, password, localFilePath, remoteFilePath);
exist(hostName, username, password, remoteFilePath);
download(hostName, username, password, localFilePath,remoteFilePath);
//move(hostName, username, password, remoteFilePath, remoteTempFilePath);
//delete(hostName, username, password, remoteFilePath);
}
/**
* Method to upload a file in Remote server
*
* #param hostName
* HostName of the server
* #param username
* UserName to login
* #param password
* Password to login
* #param localFilePath
* LocalFilePath. Should contain the entire local file path -
* Directory and Filename with \\ as separator
* #param remoteFilePath
* remoteFilePath. Should contain the entire remote file path -
* Directory and Filename with / as separator
*/
public static void upload(String hostName, String username, String password, String localFilePath, String remoteFilePath) {
File file = new File(localFilePath);
if (!file.exists())
throw new RuntimeException("Error. Local file not found");
StandardFileSystemManager manager = new StandardFileSystemManager();
try {
manager.init();
// Create local file object
FileObject localFile = manager.resolveFile(file.getAbsolutePath());
// Create remote file object
FileObject remoteFile = manager.resolveFile(createConnectionString(hostName, username, password, remoteFilePath), createDefaultOptions());
/*
* use createDefaultOptions() in place of fsOptions for all default
* options - Ashok.
*/
// Copy local file to sftp server
remoteFile.copyFrom(localFile, Selectors.SELECT_SELF);
System.out.println("File upload success");
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
manager.close();
}
}
public static boolean move(String hostName, String username, String password, String remoteSrcFilePath, String remoteDestFilePath){
StandardFileSystemManager manager = new StandardFileSystemManager();
try {
manager.init();
// Create remote object
FileObject remoteFile = manager.resolveFile(createConnectionString(hostName, username, password, remoteSrcFilePath), createDefaultOptions());
FileObject remoteDestFile = manager.resolveFile(createConnectionString(hostName, username, password, remoteDestFilePath), createDefaultOptions());
if (remoteFile.exists()) {
remoteFile.moveTo(remoteDestFile);;
System.out.println("Move remote file success");
return true;
}
else{
System.out.println("Source file doesn't exist");
return false;
}
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
manager.close();
}
}
/**
* Method to download the file from remote server location
*
* #param hostName
* HostName of the server
* #param username
* UserName to login
* #param password
* Password to login
* #param localFilePath
* LocalFilePath. Should contain the entire local file path -
* Directory and Filename with \\ as separator
* #param remoteFilePath
* remoteFilePath. Should contain the entire remote file path -
* Directory and Filename with / as separator
*/
public static void download(String hostName, String username, String password, String localFilePath, String remoteFilePath) {
StandardFileSystemManager manager = new StandardFileSystemManager();
try {
manager.init();
// Append _downlaod_from_sftp to the given file name.
//String downloadFilePath = localFilePath.substring(0, localFilePath.lastIndexOf(".")) + "_downlaod_from_sftp" + localFilePath.substring(localFilePath.lastIndexOf("."), localFilePath.length());
// Create local file object. Change location if necessary for new downloadFilePath
FileObject localFile = manager.resolveFile(localFilePath);
// Create remote file object
FileObject remoteFile = manager.resolveFile(createConnectionString(hostName, username, password, remoteFilePath), createDefaultOptions());
// Copy local file to sftp server
localFile.copyFrom(remoteFile, Selectors.SELECT_SELF);
System.out.println("File download success");
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
manager.close();
}
}
/**
* Method to delete the specified file from the remote system
*
* #param hostName
* HostName of the server
* #param username
* UserName to login
* #param password
* Password to login
* #param localFilePath
* LocalFilePath. Should contain the entire local file path -
* Directory and Filename with \\ as separator
* #param remoteFilePath
* remoteFilePath. Should contain the entire remote file path -
* Directory and Filename with / as separator
*/
public static void delete(String hostName, String username, String password, String remoteFilePath) {
StandardFileSystemManager manager = new StandardFileSystemManager();
try {
manager.init();
// Create remote object
FileObject remoteFile = manager.resolveFile(createConnectionString(hostName, username, password, remoteFilePath), createDefaultOptions());
if (remoteFile.exists()) {
remoteFile.delete();
System.out.println("Delete remote file success");
}
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
manager.close();
}
}
// Check remote file is exist function:
/**
* Method to check if the remote file exists in the specified remote
* location
*
* #param hostName
* HostName of the server
* #param username
* UserName to login
* #param password
* Password to login
* #param remoteFilePath
* remoteFilePath. Should contain the entire remote file path -
* Directory and Filename with / as separator
* #return Returns if the file exists in the specified remote location
*/
public static boolean exist(String hostName, String username, String password, String remoteFilePath) {
StandardFileSystemManager manager = new StandardFileSystemManager();
try {
manager.init();
// Create remote object
FileObject remoteFile = manager.resolveFile(createConnectionString(hostName, username, password, remoteFilePath), createDefaultOptions());
System.out.println("File exist: " + remoteFile.exists());
return remoteFile.exists();
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
manager.close();
}
}
/**
* Generates SFTP URL connection String
*
* #param hostName
* HostName of the server
* #param username
* UserName to login
* #param password
* Password to login
* #param remoteFilePath
* remoteFilePath. Should contain the entire remote file path -
* Directory and Filename with / as separator
* #return concatenated SFTP URL string
*/
public static String createConnectionString(String hostName, String username, String password, String remoteFilePath) {
if(remoteFilePath.startsWith("/")||remoteFilePath.startsWith("\\"))
remoteFilePath=remoteFilePath.substring(1);
return "sftp://" + username + ":" + password + "#" + hostName + "/" + remoteFilePath;
}
/**
* Method to setup default SFTP config
*
* #return the FileSystemOptions object containing the specified
* configuration options
* #throws FileSystemException
*/
public static FileSystemOptions createDefaultOptions() throws FileSystemException {
// Create SFTP options
FileSystemOptions opts = new FileSystemOptions();
// SSH Key checking
SftpFileSystemConfigBuilder.getInstance().setStrictHostKeyChecking(opts, "no");
/*
* Using the following line will cause VFS to choose File System's Root
* as VFS's root. If I wanted to use User's home as VFS's root then set
* 2nd method parameter to "true"
*/
// Root directory set to user home
SftpFileSystemConfigBuilder.getInstance().setUserDirIsRoot(opts, false);
// Timeout is count by Milliseconds
SftpFileSystemConfigBuilder.getInstance().setTimeout(opts, 10000);
return opts;
}
}
Please specify the file location as following and check
If it is local file,
file:///home/someuser/somedir
file:///C:/DocumentsandSettings
file://///somehost/test/text.xml
Or if it is ftp,
> ftp://myusername:mypassword#hostname/test/test.tar.gz
Your password has "#".
You need escape, try replace "#" to "%40".
Your password contains a #, thus concatenation creates an invalid connection string: sftp://username:p#ssword#hostName
It must be encoded as sftp://username:p%40ssword#hostName
Instead of concatenation, create a java.net.URI to handle proper password encoding
String userInfo = user + ":" + passwd;
URI uri = new URI("sftp", userInfo, host, -1, path, null, null);
Detail: https://stackoverflow.com/a/29568361/912046
I am trying to sent an email using my company's mail server. But I am getting the following exception
Caused by: com.sun.mail.smtp.SMTPSendFailedException: 530 5.7.1 Client was not authenticated
at com.sun.mail.smtp.SMTPTransport.issueSendCommand(SMTPTransport.java:1388)
at com.sun.mail.smtp.SMTPTransport.mailFrom(SMTPTransport.java:959)
at com.sun.mail.smtp.SMTPTransport.sendMessage(SMTPTransport.java:583)
at javax.mail.Transport.send0(Transport.java:169)
at javax.mail.Transport.send(Transport.java:98)
Here is my sample code,
Properties props = System.getProperties();
// Setup mail server
props.put("mail.smtp.host", "example.server.com");
props.put("mail.smtp.auth", "true");
props.put("mail.debug", "true");
props.put("mail.smtp.port", "25");
// Get session
//Session session = Session.getDefaultInstance(props, null);
Session session = Session.getDefaultInstance(props,
new javax.mail.Authenticator() {
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication("username", "password");
}
});
// Define message
MimeMessage message = new MimeMessage(session);
// Set the from address
message.setFrom(new InternetAddress(from));
// Set the to address
message.addRecipient(Message.RecipientType.TO, new InternetAddress(to));
// Set the subject
message.setSubject("Hello JavaMail");
// Set the content
message.setText("Welcome to JavaMail");
// Send message
Transport.send(message);
What piece of code is wrong?
As as username and password , I am using my company's email address and password.
The 5.7.1 is probably caused by exchange and not your code. You may just need to enable relaying on the server. Either for anonymous users or from a certain IP address. I'm not an expert on Exchange but I have got this working before. Here is the last solution I tested that works:
If a 5.7.1 error is encountered when trying to send an email via SMTP on an exchange server when the user has been authenticated..
For ref the issue you just had was caused by a setting on the Exchange 2007 server – this would not normally be a problem on 2003 server
Fixed by doing below...
You can set this authentication setting via the GUI
In Server configuration / Hub Transport / Default <ServerName>
Right click, properties, Permission Groups
Check "Anonymous users" and then click OK
Obviously anon users is not too secure but you could see if this solves the problem.
When I will use a MS Exhange SMTP Server to send an email, I use the above maven dependency.
<dependency>
<groupId>com.microsoft.ews-java-api</groupId>
<artifactId>ews-java-api</artifactId>
<version>2.0</version>
</dependency>
For that reason I created a class that represents an email client for MS Exchange Servers. I use log4j for logging.
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
Below the MS Exchange client class (I use the builder pattern for the construction of the object for thread safety),
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import microsoft.exchange.webservices.data.core.ExchangeService;
import microsoft.exchange.webservices.data.core.enumeration.misc.ExchangeVersion;
import microsoft.exchange.webservices.data.core.exception.service.local.ServiceLocalException;
import microsoft.exchange.webservices.data.core.service.item.EmailMessage;
import microsoft.exchange.webservices.data.credential.ExchangeCredentials;
import microsoft.exchange.webservices.data.credential.WebCredentials;
import microsoft.exchange.webservices.data.property.complex.MessageBody;
import org.apache.log4j.Logger;
/**
* A client to connect to a MS Exchange SMTP Server.
*/
public final class ExchangeClient {
private static final Logger LOGGER = Logger.getLogger(ExchangeClient.class);
private final String hostname;
private final ExchangeVersion exchangeVersion;
private final String domain;
private final String username;
private final String password;
private final String subject;
private final String recipientTo;
private final List<String> recipientCc;
private final List<String> recipientBcc;
private final List<String> attachments;
private final String message;
private ExchangeClient(ExchangeClientBuilder builder) {
this.hostname = builder.hostname;
this.exchangeVersion = builder.exchangeVersion;
this.domain = builder.domain;
this.username = builder.username;
this.password = builder.password;
this.subject = builder.subject;
this.recipientTo = builder.recipientTo;
this.recipientCc = builder.recipientCc;
this.recipientBcc = builder.recipientBcc;
this.attachments = builder.attachments;
this.message = builder.message;
}
public static class ExchangeClientBuilder {
private String hostname;
private ExchangeVersion exchangeVersion;
private String domain;
private String username;
private String password;
private String subject;
private String recipientTo;
private List<String> recipientCc;
private List<String> recipientBcc;
private List<String> attachments;
private String message;
public ExchangeClientBuilder() {
this.exchangeVersion = ExchangeVersion.Exchange2010_SP1;
this.hostname = "";
this.username = "";
this.password = "";
this.subject = "";
this.recipientTo = "";
this.recipientCc = new ArrayList<>(0);
this.recipientBcc = new ArrayList<>(0);
this.attachments = new ArrayList<>(0);
this.message = "";
}
/**
* The hostname of the Exchange Web Service. It will be used for
* connecting with URI https://hostname/ews/exchange.asmx
*
* #param hostname the hostname of the MS Exchange Smtp Server.
* #return the builder for chain usage.
*/
public ExchangeClientBuilder hostname(String hostname) {
this.hostname = hostname;
return this;
}
/**
* The Exchange Web Server version.
*
* #param exchangeVersion the Exchange Web Server version.
* #return the builder for chain usage.
*/
public ExchangeClientBuilder exchangeVersion(ExchangeVersion exchangeVersion) {
this.exchangeVersion = exchangeVersion;
return this;
}
/**
* The domain of the MS Exchange Smtp Server.
*
* #param domain the domain of the Active Directory. The first part of
* the username. For example: MYDOMAIN\\username, set the MYDOMAIN.
* #return the builder for chain usage.
*/
public ExchangeClientBuilder domain(String domain) {
this.domain = domain;
return this;
}
/**
* The username of the MS Exchange Smtp Server. The second part of the
* username. For example: MYDOMAIN\\username, set the username.
*
* #param username the username of the MS Exchange Smtp Server.
* #return the builder for chain usage.
*/
public ExchangeClientBuilder username(String username) {
this.username = username;
return this;
}
/**
* The password of the MS Exchange Smtp Server.
*
* #param password the password of the MS Exchange Smtp Server.
* #return the builder for chain usage.
*/
public ExchangeClientBuilder password(String password) {
this.password = password;
return this;
}
/**
* The subject for this send.
*
* #param subject the subject for this send.
* #return the builder for chain usage.
*/
public ExchangeClientBuilder subject(String subject) {
this.subject = subject;
return this;
}
/**
* The recipient for this send.
*
* #param recipientTo the recipient for this send.
* #return the builder for chain usage.
*/
public ExchangeClientBuilder recipientTo(String recipientTo) {
this.recipientTo = recipientTo;
return this;
}
/**
* You can specify one or more email address that will be used as cc
* recipients.
*
* #param recipientCc the first cc email address.
* #param recipientsCc the other cc email address for this send.
* #return the builder for chain usage.
*/
public ExchangeClientBuilder recipientCc(String recipientCc, String... recipientsCc) {
// Prepare the list.
List<String> recipients = new ArrayList<>(1 + recipientsCc.length);
recipients.add(recipientCc);
recipients.addAll(Arrays.asList(recipientsCc));
// Set the list.
this.recipientCc = recipients;
return this;
}
/**
* You can specify a list with email addresses that will be used as cc
* for this email send.
*
* #param recipientCc the list with email addresses that will be used as
* cc for this email send.
* #return the builder for chain usage.
*/
public ExchangeClientBuilder recipientCc(List<String> recipientCc) {
this.recipientCc = recipientCc;
return this;
}
/**
* You can specify one or more email address that will be used as bcc
* recipients.
*
* #param recipientBcc the first bcc email address.
* #param recipientsBcc the other bcc email address for this send.
* #return the builder for chain usage.
*/
public ExchangeClientBuilder recipientBcc(String recipientBcc, String... recipientsBcc) {
// Prepare the list.
List<String> recipients = new ArrayList<>(1 + recipientsBcc.length);
recipients.add(recipientBcc);
recipients.addAll(Arrays.asList(recipientsBcc));
// Set the list.
this.recipientBcc = recipients;
return this;
}
/**
* You can specify a list with email addresses that will be used as bcc
* for this email send.
*
* #param recipientBcc the list with email addresses that will be used
* as bcc for this email send.
* #return the builder for chain usage.
*/
public ExchangeClientBuilder recipientBcc(List<String> recipientBcc) {
this.recipientBcc = recipientBcc;
return this;
}
/**
* You can specify one or more email address that will be used as cc
* recipients.
*
* #param attachment the first attachment.
* #param attachments the other attachments for this send.
* #return the builder for chain usage.
*/
public ExchangeClientBuilder attachments(String attachment, String... attachments) {
// Prepare the list.
List<String> attachmentsToUse = new ArrayList<>(1 + attachments.length);
attachmentsToUse.add(attachment);
attachmentsToUse.addAll(Arrays.asList(attachments));
// Set the list.
this.attachments = attachmentsToUse;
return this;
}
/**
* You can specify a list with email attachments that will be used for
* this email send.
*
* #param attachments the list with email attachments that will be used
* for this email send.
* #return the builder for chain usage.
*/
public ExchangeClientBuilder attachments(List<String> attachments) {
this.attachments = attachments;
return this;
}
/**
* The body of the email message.
*
* #param message the body of the email message.
* #return the builder for chain usage.
*/
public ExchangeClientBuilder message(String message) {
this.message = message;
return this;
}
/**
* Build a mail.
*
* #return an EmailApacheUtils object.
*/
public ExchangeClient build() {
return new ExchangeClient(this);
}
}
public boolean sendExchange() {
// The Exchange Server Version.
ExchangeService exchangeService = new ExchangeService(exchangeVersion);
// Credentials to sign in the MS Exchange Server.
ExchangeCredentials exchangeCredentials = new WebCredentials(username, password, domain);
exchangeService.setCredentials(exchangeCredentials);
// URL of exchange web service for the mailbox.
try {
exchangeService.setUrl(new URI("https://" + hostname + "/ews/Exchange.asmx"));
} catch (URISyntaxException ex) {
LOGGER.error("An exception occured while creating the uri for exchange service.", ex);
return false;
}
// The email.
EmailMessage emailMessage;
try {
emailMessage = new EmailMessage(exchangeService);
emailMessage.setSubject(subject);
emailMessage.setBody(MessageBody.getMessageBodyFromText(message));
} catch (Exception ex) {
LOGGER.error("An exception occured while setting the email message.", ex);
return false;
}
// TO recipient.
try {
emailMessage.getToRecipients().add(recipientTo);
} catch (ServiceLocalException ex) {
LOGGER.error("An exception occured while sstting the TO recipient(" + recipientTo + ").", ex);
return false;
}
// CC recipient.
for (String recipient : recipientCc) {
try {
emailMessage.getCcRecipients().add(recipient);
} catch (ServiceLocalException ex) {
LOGGER.error("An exception occured while sstting the CC recipient(" + recipient + ").", ex);
return false;
}
}
// BCC recipient
for (String recipient : recipientBcc) {
try {
emailMessage.getBccRecipients().add(recipient);
} catch (ServiceLocalException ex) {
LOGGER.error("An exception occured while sstting the BCC recipient(" + recipient + ").", ex);
return false;
}
}
// Attachements.
for (String attachmentPath : attachments) {
try {
emailMessage.getAttachments().addFileAttachment(attachmentPath);
} catch (ServiceLocalException ex) {
LOGGER.error("An exception occured while setting the attachment.", ex);
return false;
}
}
try {
emailMessage.send();
LOGGER.debug("An email is send.");
} catch (Exception ex) {
LOGGER.error("An exception occured while sending an email.", ex);
return false;
}
return true;
}
}
A working example,
// import microsoft.exchange.webservices.data.core.enumeration.misc.ExchangeVersion;
ExchangeClient client = new ExchangeClient.ExchangeClientBuilder()
.hostname("webmail.domainOfWeb.com")
.exchangeVersion(ExchangeVersion.Exchange2010)
.domain("ActiveDirectoryDomain")
.username("ActiveDirectoryUsername")
.password("ActiveDirectoryPassword")
.recipientTo("recipient#whatever.com")
.recipientCc("recipient#whatever.com") // Ignore it in case you will not use Cc recipients.
.recipientBcc("recipient#whatever.com") // Ignore it in case you will not use Bcc recipients.
.attachments("/home/username/image.png") // Ignore it in case you will not use attachements.
.subject("Test Subject")
.message("Test Message")
.build();
client.sendExchange();
Mail.jar (Version 1.4.0) has a compatibility issue with MS Exchange Server and throws 530 5.7.1 Client was not authenticated, even when Username and password are configured.
Upgrading the mail API to 1.4.4 OR 1.4.7 should resolve the issue.
Mail API's 1.4.7 can be download from the following URL: http://www.oracle.com/technetwork/java/javamail/index.html
In some companies, the Exchange server SMTP support is disable and you cannot ask them to enable it. In these cases, a reasonable solution is this one:
http://davmail.sourceforge.net/
Simple Java Mail worked for me. The only thing you have to check is for correct hostname, username, port and password TransportStrategy.SMTP_TLS:
new Mailer(host, port, username, password, TransportStrategy.SMTP_TLS).sendMail(email);
I had to use javamail + exchange. The messages returned were helpless.
Thanks to the stack, I got some hints.
Add this to your code
props.put("mail.smtp.starttls.enable","true");
Think of adding the certificates of the machines used too.
To find them, just go to your browser, export them and import to the cacerts file in use.
Please use the following code parts instead of Transport.send(message);
MimeMessage message = new MimeMessage(session);
message.saveChanges();
Transport transport = session.getTransport("smtp");
transport.connect(host, "user", "pwd");
transport.sendMessage(message, message.getAllRecipients());
transport.close();
I have tested in the local and it is working
The ews-java-api package is at end of life.
From https://github.com/OfficeDev/ews-java-api
Starting July 19th 2018, Exchange Web Services (EWS) will no longer receive feature updates. While the service will continue to receive security updates and certain non-security updates, product design and features will remain unchanged. This change also applies to the EWS SDKs for Java and .NET. More information here: https://developer.microsoft.com/en-us/graph/blogs/upcoming-changes-to-exchange-web-services-ews-api-for-office-365/