Embedding Apache FTP Server : Not able to login with 40 user Concurrently - spring

I am using this Embedded server for integration testing of Spring-integration-ftp.
I have to connect this ftp server to 40 spring integration ftp service I have also added ConcurrentLoginPermission to 50 still I am getting
SENT: 421 Maximum login limit has been reached. Error
Here is the code Which I have written for the embedded server.
protected static final Integer FTP_PORT = 2221;
protected static final String FTP_USER = "admin";
protected static final String FTP_PASSWORD = "admin";
protected static final String FTP_HOME_DIRECTORY = "src/test/resources/xml/checkpoint";```
```PropertiesUserManagerFactory userManagerFactory = new PropertiesUserManagerFactory();
UserManager userManager = userManagerFactory.createUserManager();
BaseUser user = new BaseUser();
user.setName(FTP_USER);
user.setPassword(FTP_PASSWORD);
user.setHomeDirectory(FTP_HOME_DIRECTORY);
List<Authority> authorities = new ArrayList<>();
authorities.add(new WritePermission());
authorities.add(new TransferRatePermission(50, 50));
authorities.add(new ConcurrentLoginPermission(50, 50));
user.setAuthorities(authorities);
try {
userManager.save(user);
} catch (FtpException e) {
e.printStackTrace();
}
ListenerFactory listenerFactory = new ListenerFactory();
listenerFactory.setPort(FTP_PORT);
FtpServerFactory factory = new FtpServerFactory();
factory.setUserManager(userManager);
factory.addListener("default", listenerFactory.createListener());
FtpServer server = factory.createServer();
try {
server.start();
} catch (FtpException e) {
e.printStackTrace();
}
FakeFtpServer fakeFtpServer = new FakeFtpServer();
fakeFtpServer.setServerControlPort(2222);
FileSystem fileSystem = new UnixFakeFileSystem();
fileSystem.add(new DirectoryEntry("/FTP_TEST"));
fakeFtpServer.setFileSystem(fileSystem);
UserAccount userAccount = new UserAccount("vioohcentral", "vioohcentral", "/FTP_TEST");
fakeFtpServer.addUserAccount(userAccount);
fakeFtpServer.start();

Related

Map LDAP groups to OAuth2 UserDetails in Spring Boot web app

After failed attempts to get CAS Single Sign Out working, we decided to try out OAuth2 using OpenID Connect with our Spring Boot web apps. Now we only need OAuth for SSO and to provide authentication - we're not storing username/password in a db or anything. We are using Google LDAP to grant authorities. I cannot find any solid example of using Google LDAP for authorities with OAuth2. My OAuth2 code is pretty simple so far. Here's my WebSecurityConfig so far:
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests(authorizeRequests -> authorizeRequests
.mvcMatchers("/home").permitAll()
.anyRequest().authenticated())
.oauth2Login(oauthLogin -> oauthLogin.permitAll());
}
and one of my endpoints that works:
#GetMapping("/user/me")
public String userDetails(#AuthenticationPrincipal OAuth2User user) {
Map<String, Object> attributes = user.getAttributes();
String username = (String) attributes.get("email");
return username;
}
Now here is what I used with my CAS and LDAP config. This block of code would pull all LDAP groups and map them to roles using SimpleGrantedAuthority. I've tried a ton of different configs, but nothing has worked.
private LdapContext getLdapReadContext(){
LdapContext ctx = null;
try{
Hashtable<String,String> env = new Hashtable<>();
env.put(Context.INITIAL_CONTEXT_FACTORY,ldapCtxFactory);
env.put(Context.SECURITY_AUTHENTICATION,"Simple");
env.put(Context.SECURITY_PRINCIPAL,ldapUsername);
env.put(Context.SECURITY_CREDENTIALS,ldapPassword);
env.put(Context.PROVIDER_URL,ldapURL);
ctx = new InitialLdapContext(env,null);
}catch(NamingException e){
e.printStackTrace();
}
return ctx;
}
public List<String> Groups(LdapContext ctx, AttributePrincipal principal){
String uid = "uid";
List<String> groups = new LinkedList<>();
NamingEnumeration answer = null;
if(principal!=null){
Map attributes =principal.getAttributes();
if(attributes.get(uid)!=null){
uid=attributes.get(uid).toString();
try{
SearchControls constraints = new SearchControls();
constraints.setSearchScope(SearchControls.SUBTREE_SCOPE);
String searchFilter = "(&(objectClass=groupOfNames)(member=uid="+uid+","+ldapBase+"))";
String[] attrIDs = {"cn"};
constraints.setReturningAttributes(attrIDs);
answer = ctx.search(ldapGroupBase,searchFilter,constraints);
while (answer.hasMore()){
Attributes attrs = ((SearchResult)answer.next()).getAttributes();
groups.add(attrs.get("cn").toString());
}
}catch(Exception ignored){
}finally{
if (answer !=null){
try{
answer.close();
}catch(Exception ignored){
}
}
if (ctx != null){
try{
ctx.close();
}catch(Exception ignored){
}
}
}
}
}
if (groups.isEmpty()){
groups.add("STUDENT");
}
return groups;
}
#Override
public UserDetails loadUserDetails (#Autowired Authentication authentication) throws UsernameNotFoundException {
CasAssertionAuthenticationToken casAssertionAuthenticationToken = (CasAssertionAuthenticationToken) authentication;
AttributePrincipal principal = casAssertionAuthenticationToken.getAssertion().getPrincipal();
Map attributes = principal.getAttributes();
String user = (String)attributes.get("username");
String email = (String)attributes.get("email");
String fname = (String)attributes.get("fname");
String lname = (String)attributes.get("lname");
String VNumber = (String)attributes.get("UDC_IDENTIFIER");
String uid = (String)attributes.get("uid");
String role = "user";
String username = authentication.getName();
List<String> grouplist = null;
grouplist = Groups(getLdapReadContext(), principal);
Collection<SimpleGrantedAuthority> collection = new ArrayList<SimpleGrantedAuthority>();
for (int i =0; i<grouplist.size(); i++) {
collection.add(new SimpleGrantedAuthority((grouplist.get(i)).substring(4)));
}
return new User(username, "",collection);
}

Spring integration TCP Server multiple connections of more than 5

I'm using the following version of Spring Boot and Spring integration now.
spring.boot.version 2.3.4.RELEASE
spring-integration 5.3.2.RELEASE
My requirement is to create a TCP client server communication and i'm using spring integration for the same. The spike works fine for a single communication between client and server and also works fine for exactly 5 concurrent client connections.
The moment i have increased the concurrent client connections from 5 to any arbitary numbers, it doesn't work but the TCP server accepts only 5 connections.
I have used the 'ThreadAffinityClientConnectionFactory' mentioned by #Gary Russell in one of the earlier comments ( for similar requirements ) but still doesn't work.
Below is the code i have at the moment.
#Slf4j
#Configuration
#EnableIntegration
#IntegrationComponentScan
public class SocketConfig {
#Value("${socket.host}")
private String clientSocketHost;
#Value("${socket.port}")
private Integer clientSocketPort;
#Bean
public TcpOutboundGateway tcpOutGate(AbstractClientConnectionFactory connectionFactory) {
TcpOutboundGateway gate = new TcpOutboundGateway();
//connectionFactory.setTaskExecutor(taskExecutor());
gate.setConnectionFactory(clientCF());
return gate;
}
#Bean
public TcpInboundGateway tcpInGate(AbstractServerConnectionFactory connectionFactory) {
TcpInboundGateway inGate = new TcpInboundGateway();
inGate.setConnectionFactory(connectionFactory);
inGate.setRequestChannel(fromTcp());
return inGate;
}
#Bean
public MessageChannel fromTcp() {
return new DirectChannel();
}
// Outgoing requests
#Bean
public ThreadAffinityClientConnectionFactory clientCF() {
TcpNetClientConnectionFactory tcpNetClientConnectionFactory = new TcpNetClientConnectionFactory(clientSocketHost, serverCF().getPort());
tcpNetClientConnectionFactory.setSingleUse(true);
ThreadAffinityClientConnectionFactory threadAffinityClientConnectionFactory = new ThreadAffinityClientConnectionFactory(
tcpNetClientConnectionFactory);
// Tested with the below too.
// threadAffinityClientConnectionFactory.setTaskExecutor(taskExecutor());
return threadAffinityClientConnectionFactory;
}
// Incoming requests
#Bean
public AbstractServerConnectionFactory serverCF() {
log.info("Server Connection Factory");
TcpNetServerConnectionFactory tcpNetServerConnectionFactory = new TcpNetServerConnectionFactory(clientSocketPort);
tcpNetServerConnectionFactory.setSerializer(new CustomSerializer());
tcpNetServerConnectionFactory.setDeserializer(new CustomDeserializer());
tcpNetServerConnectionFactory.setSingleUse(true);
return tcpNetServerConnectionFactory;
}
#Bean
public TaskExecutor taskExecutor () {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(50);
executor.setMaxPoolSize(100);
executor.setQueueCapacity(50);
executor.setAllowCoreThreadTimeOut(true);
executor.setKeepAliveSeconds(120);
return executor;
}
}
Did anyone had the same issue with having multiple concurrent Tcp client connections of more than 5 ?
Thanks
Client Code:
#Component
#Slf4j
#RequiredArgsConstructor
public class ScheduledTaskService {
// Timeout in milliseconds
private static final int SOCKET_TIME_OUT = 18000;
private static final int BUFFER_SIZE = 32000;
private static final int ETX = 0x03;
private static final String HEADER = "ABCDEF ";
private static final String data = "FIXED DARATA"
private final AtomicInteger atomicInteger = new AtomicInteger();
#Async
#Scheduled(fixedDelay = 100000)
public void sendDataMessage() throws IOException, InterruptedException {
int numberOfRequests = 10;
Callable<String> executeMultipleSuccessfulRequestTask = () -> socketSendNReceive();
final Collection<Callable<String>> callables = new ArrayList<>();
IntStream.rangeClosed(1, numberOfRequests).forEach(i-> {
callables.add(executeMultipleSuccessfulRequestTask);
});
ExecutorService executorService = Executors.newFixedThreadPool(numberOfRequests);
List<Future<String>> taskFutureList = executorService.invokeAll(callables);
List<String> strings = taskFutureList.stream().map(future -> {
try {
return future.get(20000, TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
} catch (TimeoutException e) {
e.printStackTrace();
}
return "";
}).collect(Collectors.toList());
strings.forEach(string -> log.info("Message received from the server: {} ", string));
}
public String socketSendNReceive() throws IOException{
int requestCounter = atomicInteger.incrementAndGet();
String host = "localhost";
int port = 8000;
Socket socket = new Socket();
InetSocketAddress address = new InetSocketAddress(host, port);
socket.connect(address, SOCKET_TIME_OUT);
socket.setSoTimeout(SOCKET_TIME_OUT);
//Send the message to the server
OutputStream os = socket.getOutputStream();
BufferedOutputStream bos = new BufferedOutputStream(os);
bos.write(HEADER.getBytes());
bos.write(data.getBytes());
bos.write(ETX);
bos.flush();
// log.info("Message sent to the server : {} ", envio);
//Get the return message from the server
InputStream is = socket.getInputStream();
String response = receber(is);
log.info("Received response");
return response;
}
private String receber(InputStream in) throws IOException {
final StringBuffer stringBuffer = new StringBuffer();
int readLength;
byte[] buffer;
buffer = new byte[BUFFER_SIZE];
do {
if(Objects.nonNull(in)) {
log.info("Input Stream not null");
}
readLength = in.read(buffer);
log.info("readLength : {} ", readLength);
if(readLength > 0){
stringBuffer.append(new String(buffer),0,readLength);
log.info("String ******");
}
} while (buffer[readLength-1] != ETX);
buffer = null;
stringBuffer.deleteCharAt(resposta.length()-1);
return stringBuffer.toString();
}
}
Since you are opening the connections all at the same time, you need to increase the backlog property on the server connection factory.
It defaults to 5.
/**
* The number of sockets in the connection backlog. Default 5;
* increase if you expect high connection rates.
* #param backlog The backlog to set.
*/
public void setBacklog(int backlog) {

How To Config Lettuce Redis cluster Async Connection Pool

I'm configuring my lettuce rediscluster pool. When I configure it according to the official documentation, the connection pool cannot be initialized properly and I can't get the connection. The official docs state:
RedisClusterClient clusterClient =
RedisClusterClient.create(RedisURI.create(host, port));
AsyncPool<StatefulRedisConnection<String, String>> pool = AsyncConnectionPoolSupport.createBoundedObjectPool( () -> clusterClient.connectAsync(StringCodec.UTF8), BoundedPoolConfig.create());
// execute work
CompletableFuture<String> setResult = pool.acquire().thenCompose(connection -> {
RedisAsyncCommands<String, String> async = connection.async();
async.set("key", "value");
return async.async.set("key2", "value2").whenComplete((s, throwable) -> pool.release(c));
});
// terminating
pool.closeAsync();
// after pool completion
client.shutdownAsync();
this config not work in my environment .then i add minIdle config :
final BoundedPoolConfig.Builder builder = BoundedPoolConfig.builder();
builder.minIdle(9);
It worked at the beginning, but when I loop through the connection pool and send commands from multiple times, the following exeception is thrown:
java.util.concurrent.ExecutionException: java.lang.IllegalStateException: AsyncPool is closed at java.util.concurrent.CompletableFuture.reportGet(CompletableFuture.java:357) at java.util.concurrent.CompletableFuture.get(CompletableFuture.java:1895)
Here are all my code:
private String passwd = "xxxxx";
private String ip = "10.0.0.204";
;
#Bean
#Scope("singleton")
public ClientResources clientResources() {
final DefaultClientResources defaultClientResources = DefaultClientResources.builder()
.ioThreadPoolSize(4)
.computationThreadPoolSize(4)
.build();
return defaultClientResources;
}
#Bean(destroyMethod = "shutdown")
#Scope("singleton")
public RedisClusterClient clusterClient(ClientResources clientResources) {
final String ip = "10.0.0.204";
final String passwd = "dingXiang123";
final RedisURI redisURI1 = RedisURI.Builder.redis(ip, 7001).withPassword(passwd).build();
final RedisURI redisURI2 = RedisURI.Builder.redis(ip, 7002).withPassword(passwd).build();
final RedisURI redisURI3 = RedisURI.Builder.redis(ip, 7003).withPassword(passwd).build();
final RedisURI redisURI4 = RedisURI.Builder.redis(ip, 7004).withPassword(passwd).build();
final RedisURI redisURI5 = RedisURI.Builder.redis(ip, 7005).withPassword(passwd).build();
final RedisURI redisURI6 = RedisURI.Builder.redis(ip, 7006).withPassword(passwd).build();
RedisClusterClient clusterClient = null;
try {
final List<RedisURI> redisURIS = Arrays.asList(redisURI1, redisURI2, redisURI3, redisURI4, redisURI5, redisURI6);
clusterClient = RedisClusterClient.create(clientResources, redisURIS);
ClusterTopologyRefreshOptions topologyRefreshOptions = ClusterTopologyRefreshOptions.builder()
.enableAdaptiveRefreshTrigger(ClusterTopologyRefreshOptions.RefreshTrigger.MOVED_REDIRECT, ClusterTopologyRefreshOptions.RefreshTrigger.PERSISTENT_RECONNECTS)
//连接池refresh超时时间
.adaptiveRefreshTriggersTimeout(Duration.ofMinutes(3))
.build();
clusterClient.setOptions(ClusterClientOptions.builder()
.topologyRefreshOptions(topologyRefreshOptions)
.autoReconnect(true)
.pingBeforeActivateConnection(true)
.build());
final RedisAdvancedClusterAsyncCommands<String, String> async = clusterClient.connect().async();
final RedisFuture<String> set = async.set("aa", "aaaaa");
set.get();
log.info("客户端初始化成功");
return clusterClient;
} catch (Exception e) {
log.error("lettce客户端初始化失败,{}", e);
if (clusterClient != null) {
clusterClient.shutdown();
}
}
return null;
}
/**
* 初始化异步的 Cluter 模式链接池
*
* #param clusterClient
* #return
*/
#Bean()
#DependsOn("clusterClient")
#Scope("singleton")
public BoundedAsyncPool<StatefulRedisClusterConnection<String, String>> lettucePool(RedisClusterClient clusterClient) {
final BoundedPoolConfig.Builder builder = BoundedPoolConfig.builder();
builder.minIdle(9);
final BoundedPoolConfig boundedPoolConfig = builder.build();
final BoundedAsyncPool<StatefulRedisClusterConnection<String, String>> lettucePool = AsyncConnectionPoolSupport.createBoundedObjectPool(
() -> clusterClient.connectAsync(StringCodec.UTF8)
, boundedPoolConfig
);
log.info("连接池初始化成功");
return lettucePool;
}
/**
* 从连接池获取链接
*
* #param lettucePool
*/
#Bean
#DependsOn("lettucePool")
public CompletableFuture<StatefulRedisClusterConnection<String, String>> clusterAsync(BoundedAsyncPool<StatefulRedisClusterConnection<String, String>> lettucePool) {
final CompletableFuture<StatefulRedisClusterConnection<String, String>> acquire = lettucePool.acquire();
return acquire;
}
Have you encountered this problem again, how did you solve it?
The other point is that I don't really like redisTemplate to operate the letuce API, so I am looking for a configuration solution for the native Lettuce cluster pool.
Have you done the configuration of the original cluster pool or the use of Api before, or have seen the detailed Demo documentation, if you have, please recommend it to me (of course, I also read the official document, I may Need a Demo Application to study )

How to reuse a SSH (Jsch) session created in an AsyncTask in another class

I'm a Android & Java newbie and here is my situation:
I'm trying to create an app which connects to a Beaglebone Black using a ssh connection and then controls some peripherals connected to the BBB by issuing commands coming from an Android device.
I'm opening (successfully) an ssh session in an AsyncTask while the user sees an splash screen, if the connection was successful the user will get a confirmation and then will be able to send predefined commands by clicking some available buttons.
What I want to do next is left the session opened and then create a new channel (exec or shell ) each time I wish to issue a command and wait for the response from the BBB, but I don´t know how to reuse such ssh session outside the AsynkTask.
is that even possible?
I'm using Android Studio 0.8.2 and Jsch 0.1.51, my code is as follows:
public class SplashScreen extends ActionBarActivity {
public static final int segundos =10;
public static final int milisegundos =segundos*1000;
public static final int delay=2;
private ProgressBar pbprogreso;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_splash_screen);
pbprogreso= (ProgressBar)findViewById(R.id.pbprogreso);
pbprogreso.setMax(maximo_progreso());
empezaranimacion();
}
public void empezaranimacion()
{
sshConnect task = new sshConnect();
task.execute(new String[] {"http:"});
new CountDownTimer(milisegundos,1000)
{
#Override
public void onTick(long milisUntilFinished){
pbprogreso.setProgress(establecer_progreso(milisUntilFinished));
}
#Override
public void onFinish(){
finish();
}
}.start();
}
public int establecer_progreso (long miliseconds)
{
return (int)((milisegundos-miliseconds)/1000);
}
public int maximo_progreso () {
return segundos-delay;
}
public class sshConnect extends AsyncTask <String, Void, String>{
ByteArrayOutputStream Baos=new ByteArrayOutputStream();
ByteArrayInputStream Bais = new ByteArrayInputStream(new byte[1000]);
#Override
protected String doInBackground(String... data) {
String host = "xxxxxxx";
String user = "root";
String pwd = "";
int port = 22;
JSch jsch = new JSch();
try {
Session session = jsch.getSession(user, host, port);
session.setPassword(pwd);
session.setConfig("StrictHostKeyChecking", "no");
session.connect();
ChannelExec channel = (ChannelExec)session.openChannel("exec");
channel.setOutputStream(Baos);
channel.setInputStream(Bais);
//Run Command
channel.setCommand("python ~/BBB_test/testconnect.py");
channel.connect();
try{Thread.sleep(3500);}catch (Exception ee){}
channel.disconnect();
//session.disconnect();
}catch (Exception e){
System.out.println(e.getMessage());
}
return Baos.toString();
}
#Override
protected void onPostExecute(String result) {
if (result.equals("Connected to BBB Baby!!\n")) {
Intent nuevofrom = new Intent(SplashScreen.this, Principal.class);
startActivity(nuevofrom);
finish();
} else {
Intent newfrom = new Intent(SplashScreen.this, ConnecError.class);
startActivity(newfrom);
finish();
}
}
}
//Here is where I want to reuse the opened session and create a new channel
public class sendCommand extends AsyncTask <String, Void, String >{
ByteArrayOutputStream Baosc=new ByteArrayOutputStream();
ByteArrayInputStream Baisc = new ByteArrayInputStream(new byte[1000])
protected String doInBackground (String... command){
try {
ChannelExec channel2 = (ChannelExec)session.openChannel("exec");
channel2.setOutputStream(Baosc);
channel2.setInputStream(Baisc);
//Run Command
channel2.setCommand("python ~/BBB_test/testgpio.py");
channel2.connect();
try{Thread.sleep(3500);}catch (Exception ee){}
channel2.disconnect();
}catch (Exception e) {
System.out.println(e.getMessage());
}
return Baosc.toString();
}
protected void onPostExecute(Long result) {
TextView txt = (TextView) findViewById(R.id.infotext);
txt.setText(result);
}
}
If something else is needed let me know! (it is the first time I ask something in a forum)
Thanks a lot for your time and support!
I managed to get what I wanted by using the recommendation from DamienKnight of creating the session outside the Asynktask class. I create a public classwith three methods to create, return and disconnect the session:
public static class cSession {
String host = "xxx.xxx.xxx.xxx";
String user = "root";
String pwd = "";
int port = 22;
JSch jsch = new JSch();
public Session Met1 (){
try {
session = jsch.getSession(user, host, port);
session.setPassword(pwd);
session.setConfig("StrictHostKeyChecking", "no");
} catch (Exception e2){
System.out.println(e2.getMessage());
}return session;
}
public Session damesession (){
return session;
}
public void close_ses(){
session.disconnect();
}
}
By doing this so, the creation of channels is flexible and I can use the methods from Jsch too.
public class sshConnect extends AsyncTask <String, Void, String>{
ByteArrayOutputStream Baos=new ByteArrayOutputStream();
ByteArrayInputStream Bais = new ByteArrayInputStream(new byte[1000]);
#Override
protected String doInBackground(String... data) {
cSession jschses = new cSession();
Session ses =null;
ses = jschses.Met1();
try {
ses.connect();
ChannelExec channel = (ChannelExec)ses.openChannel("exec");
channel.setOutputStream(Baos);
channel.setInputStream(Bais);
//Run Command
channel.setCommand("python ~/BBB_test/testconnect.py");
channel.connect();
try{Thread.sleep(3500);}catch (Exception ee){}
channel.disconnect();
//session.disconnect();
}catch (Exception e){
System.out.println(e.getMessage());
}
return Baos.toString();
}
Thanks #Damienknight!
Regards
If you are wanting to reuse the session, you dont need to reconect the channel each time. Connect it once as a shell, plugging an input and output stream into it. Use the streams to pass commands and capture output.
See the JSCH example on the JCraft website.
Channel channel=session.openChannel("shell");
channel.setInputStream(System.in);
channel.setOutputStream(System.out);
channel.connect();

Why do I get an IOException in sending an email with Gmail service?

In my android test application, after that i got the JSON file from the Google Developer Console, where i had set on the Gmail API, and that i have put it in the emulator, i get an IOException which says:
"com.google.api.client.googleapis.json.GoogleJsonResponseException:
403 Forbidden { "code" : 403, "errors" : [ {
"domain" : "usageLimits",
"message" : "Access Not Configured. Please use Google Developers Console to activate the API for your project.",
"reason" : "accessNotConfigured" } ], "message" : "Access Not Configured. Please use Google Developers Console to activate the API
for your project." }"
I think that I must use a GoogleClientSecrets object, but i haven't found its use.
Here the code:
public class MainActivity extends Activity
{
final String SCOPE = "oauth2:https://www.googleapis.com/auth/gmail.compose";
final String FILE_NAME = "TestEmail5.json";
private static final int REQUEST_RESOLVE_ERROR = 1001;
Button button;
OnClickListener sendListener = new OnClickListener()
{
#Override
public void onClick(View v)
{
new sendEmailTask().execute();
}
};
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button = (Button)findViewById(R.id.button1);
button.setOnClickListener(sendListener);
}
public static MimeMessage createEmail(String to, String from, String subject, String bodyText) throws MessagingException
{
Properties props = new Properties();
Session session = Session.getDefaultInstance(props, null);
MimeMessage email = new MimeMessage(session);
InternetAddress tAddress = new InternetAddress(to);
InternetAddress fAddress = new InternetAddress(from);
email.setFrom(new InternetAddress(from));
email.addRecipient(javax.mail.Message.RecipientType.TO, new InternetAddress(to));
email.setSubject(subject);
email.setText(bodyText);
return email;
}
public static void sendMessage(Gmail service, String userId, MimeMessage email) throws MessagingException, IOException
{
Message message = createMessageWithEmail(email);
message = service.users().messages().send(userId, message).execute();
System.out.println("Message id: " + message.getId());
System.out.println(message.toPrettyString());
}
public static Message createMessageWithEmail(MimeMessage email) throws MessagingException, IOException
{
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
email.writeTo(bytes);
String encodedEmail = Base64.encodeBase64URLSafeString(bytes.toByteArray());
Message message = new Message();
message.setRaw(encodedEmail);
return message;
}
public class sendEmailTask extends AsyncTask
{
#Override
protected Object doInBackground(Object... params)
{
HttpTransport httpTransport = new NetHttpTransport();
JsonFactory jsonFactory = new JacksonFactory();
String token = "";
AccountManager accountManager = AccountManager.get(MainActivity.this);
Account account[] = accountManager.getAccountsByType("com.google");
String accountName = account[0].name;
try
{
//GoogleClientSecrets clientSecrets = GoogleClientSecrets.load(jsonFactory, new java.io.FileReader(Environment.getExternalStorageDirectory().getAbsolutePath() + "//" + "JSON/" + FILE_NAME));
token = GoogleAuthUtil.getToken(MainActivity.this, accountName, SCOPE);
GoogleCredential credential = new GoogleCredential().setAccessToken(token);
Gmail service = new Gmail.Builder(httpTransport, jsonFactory, credential).setApplicationName("TestEmail5").build();
MimeMessage mm = createEmail("myemail", "myemail", "soggetto", "oggetto");
sendMessage(service, "myemail", mm);
}
catch (UserRecoverableAuthException e)
{
startActivityForResult(e.getIntent(), REQUEST_RESOLVE_ERROR);
}
catch (IOException e)
{
e.printStackTrace();
}
catch (GoogleAuthException e)
{
e.printStackTrace();
}
catch (MessagingException e)
{
e.printStackTrace();
}
return null;
}
};
}
You need to login to http://console.developers.google.com/ and create a project and activate the "Gmail" API for it.
Documented more at:
https://developers.google.com/gmail/api/quickstart/quickstart-java#step_1_enable_the_gmail_api

Resources