Read and Write Gmail Messages


Method sendEmail is missing. Can we have solution to fix it. I think something not config inside sendEmail method.

Nice work @Hari !! thx !
unfortunatly I have a problem with readLatestEMailBodyContent. My response body is “javax.mail.internet.MimeMultipart@1a15b789” so I can’t do what I want.
there’s a workaround or something that I can do to fix this issue ?

Can you please explain this point more in detail. As i have followed above steps and facing same issue.
Please help.

Hello.

I have implemented own keyword which will fetch latest unread gmail message with search criteria as reporting date (current) and will download
attachment to disk

following this you are able to implement send, delete etc methods

package readGmail

import java.text.DateFormat
import java.text.ParseException
import java.text.SimpleDateFormat

import javax.mail.*
import javax.mail.search.*;

import com.kms.katalon.core.annotation.Keyword
import com.kms.katalon.core.exception.StepErrorException

import internal.GlobalVariable as GlobalVariable

public class getGmail {

	public String fname

	@Keyword
	public String getGmailAttachment(){
		Date afterDate;
		String  gmailServer
		int gmailPort
		def user, password, LIMIT
		def inboxFolder, root, StartDate, EndDate

		// Maximm number of emails to access in case parameter range is too high

		LIMIT = 10

		inboxFolder = "INBOX"

		Properties props = new Properties();
		props.load(new FileInputStream(new File( "C:\\Users\\xxxx\\Desktop\\gmail\\smtp.properties" )));
		Session session = Session.getDefaultInstance(props, null);

		password = GlobalVariable.pass;
		String username = GlobalVariable.gmailUser;
		Store store = session.getStore("imaps");
		store.connect("smtp.gmail.com", "user@gmail.com", "password");

		int i = 0;
		def folder = store.getFolder(inboxFolder)

		folder.open(Folder.READ_WRITE)

		// search for all "unseen" messages
		Flags seen = new Flags(Flags.Flag.SEEN);
		FlagTerm unseenFlagTerm = new FlagTerm(seen, false);
		Message[] messages = folder.search(unseenFlagTerm);

		if (messages.length == 0){
			System.out.println("No messages found.");
			throw new com.kms.katalon.core.exception.StepErrorException("No unread mesages will found!!!");
		}


		BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));

		afterDate = new Date()
		DateFormat df = new SimpleDateFormat("dd-MM-yyyy");
		String reportDate = df.format(afterDate);
		
		int z,n;
		for(z = 0; z<messages.length; z++){
			Message message = messages[z];

			System.out.println(i + ": " + messages[i].getFrom()[0]+ "\t" + messages[i].getSubject());
			System.out.println("Wanted the content? [Y to read/Q to end]");
			System.out.println("Date : " + message.getSentDate());
			System.out.println("report date : " + reportDate);
			String messageDate = df.format(message.getSentDate());
			System.out.println("message date : " + messageDate);

			if (reportDate.equals(messageDate)){
				System.out.println("*****dates match****");
			}else{
				System.out.println("dates NOT match");
			}


			String ans = "y";
			ans=ans.toLowerCase();
			if (messageDate.equals(reportDate)) {
				Object content = messages[i].getContent();
				if (content instanceof Multipart) {
					handleMultipart((Multipart)content);
				}
				else {
					handlePart(messages[i]);
				}
			}
			else {
				throw new com.kms.katalon.core.exception.StepErrorException("dates not match!!!");
				break;
			}

		}

		//mark gmail message as read
		folder.setFlags(messages, new Flags(Flags.Flag.SEEN), true);

		folder.close(true);
		store.close();
		return fname
	}

	public String handleMultipart(Multipart multipart) throws MessagingException, IOException {
		for (int i=0; i<multipart.getCount(); i++){
			handlePart(multipart.getBodyPart(i));
		}
	}

	public String handlePart(Part part)  throws MessagingException, IOException {
		String dposition = part.getDisposition();
		String cType = part.getContentType();
		if (dposition == null) {
			System.out.println("Null"+ cType);
			if ((cType.length() >= 10) && (cType.toLowerCase().substring(0, 10).equals("text/plain"))) {
				part.writeTo(System.out);
			}
			else {
				System.out.println("Other: " + cType);
				part.writeTo(System.out);
			}
		}
		else if (dposition.equalsIgnoreCase(Part.ATTACHMENT)) {
			System.out.println("Attachment"+ part.getFileName() + " : " + cType);
			saveFile(part.getFileName(), part.getInputStream());
			fname = part.getFileName()
			println("######## DEBUG attachment ##### "+fname)
		}
		else if (dposition.equalsIgnoreCase(Part.INLINE)) {
			System.out.println("Inline"+ part.getFileName() +  " : " + cType);
			saveFile(part.getFileName(), part.getInputStream());
			fname = part.getFileName()
			println("######## DEBUG inline ##### "+fname)
		}
		else {
			System.out.println("Other dposition");
		}
	}

	public static void saveFile(String filename,InputStream input) throws IOException {
		if (filename == null) {
			filename = File.createTempFile("MailAttacheFile", ".out").getName();
		}
		System.out.println("downloadingAttachment..."+filename);
		File file = new File(filename);
		for (int i=0; file.exists(); i++) {
			file = new File(filename+i);
		}
		FileOutputStream fos = new FileOutputStream(file);
		BufferedOutputStream bos = new BufferedOutputStream(fos);
		BufferedInputStream bis = new BufferedInputStream(input);
		int fByte;
		while ((fByte = bis.read()) != -1) {
			bos.write(fByte);
		}
		bos.flush();
		bos.close();
		bis.close();
		System.out.println("done...");
	}

}

Hello, I am getting classnotfound error when invoke test suite from windows batch file, any ideas why?
It works fine when I launch test suite from Katalon Studio 6.3.3 (after allow Gmail less secure apps and enable IMAP)

Content of my batch file:
“D:\Katalon_Studio_Windows_64-6.3.3\katalon.exe” -noSplash -runMode=console -consoleLog -projectPath=“D:\Katalon-gmail\xxxCheck.prj” -retry=0 -testSuitePath=“Test Suites/xxxCheck” -executionProfile=“default” -browserType=“Chrome”

thanks

Reason:
java.lang.ClassNotFoundException: com.testwithhari.katalon.plugins.Gmail
at com.kms.katalon.core.main.CustomKeywordDelegatingMetaClass.getCustomKeywordClassAndSetMetaClass(CustomKeywordDelegatingMetaClass.java:100)
at com.kms.katalon.core.main.CustomKeywordDelegatingMetaClass.invokeStaticMethod(CustomKeywordDelegatingMetaClass.java:45)
at xxxCheck.run(xxxCheck:20)
at com.kms.katalon.core.main.ScriptEngine.run(ScriptEngine.java:194)
at com.kms.katalon.core.main.ScriptEngine.runScriptAsRawText(ScriptEngine.java:119)
at com.kms.katalon.core.main.TestCaseExecutor.runScript(TestCaseExecutor.java:337)2019-10-21 16:03:28.241 INFO c.k.katalon.core.main.TestCaseExecutor

You need -apiKey in your command to load plugins from Store.

Thanks devalex88
So, is plugin from Katalon Store is not persistent?

Hi Hari,

I tired to read the latest email content by using your method - “com.testwithhari.katalon.plugins.Gmail.readLatestEMailBodyContent” but ended up getting below error message:

groovy.lang.MissingMethodException: No signature of method: java.lang.Boolean.call() is applicable for argument types: (com.testwithhari.katalon.plugins.Gmail$_writePart_closure1) values: [com.testwithhari.katalon.plugins.Gmail$_writePart_closure1@369c9bb]
Possible solutions: wait(), any(), wait(long), and(java.lang.Boolean), any(groovy.lang.Closure), each(groovy.lang.Closure)

1 Like

Hi Ankit, I get the same error response.
Working with emails in “text/html” format that is supposed to be supported it only works for some emails.
The potential difference I noticed is that the emails which throw your error code have a clickable button attached.

Any workaround or fix to the problem would be highly appreciated. Thanks

Hello,

I wrote my own Keyword to read the content of very latest email. You can always customize it.

public class ReadEmail {

@Keyword
def String VerificationCode (String host, String username, String password) {
	try {

		Properties props = new Properties();
		props.load(new FileInputStream(new File("C:\\smtp.properties")));
		Session session = Session.getDefaultInstance(props, null);
		Store store = session.getStore("imaps");
		store.connect(host, username, password);
		Folder inbox = store.getFolder("inbox");
		inbox.open(Folder.READ_ONLY);
		int messageCount = inbox.getMessageCount();

		//System.out.println("Total Messages:- " + messageCount);

		Message[] messages = inbox.getMessages();

		//Flags seen = new Flags(Flags.Flag.SEEN);
		//Message[] messages = inbox.search(new FlagTerm(new Flags(Flags.Flag.SEEN), false));

		System.out.println("------------------------------");

		//for (int i = (messageCount-1)  ; i > 10; i--) {
		System.out.println("Mail Subject:- " + messages[messageCount-1].getSubject());
		String content = messages[messageCount-1].getContent().toString();

// to get the verification code from the entire email text
String[] code = content.split(" ", 2)

		return code[1].substring(0, 6)
		inbox.close(true);
		store.close();


	} catch (NoSuchProviderException e) {
		e.printStackTrace();
	} catch (MessagingException e) {
		e.printStackTrace();
	} catch (Exception e) {
		e.printStackTrace();
	}
}

}

1 Like

Excelent plugin Hari.
Can you kindly provide us with any resource/tutorial where we can learn about how to click a button, such as ‘Verify Email Address’ in an email

Please watch you tube video and capture the object so that you can click on it.

https://www.youtube.com/watch?v=33uDYlnBgLc

Hey Hari this video seems to be private, can you please share this link please!

But the keyword convert all the content inside the mail into a plane text. I’m not sure how I can click it

This is basically for capturing OTP or some text, If your requirement is to click on some URL after entering to inbox in that case you need write browser test script or you download the gmail App on mobile and write the script to click on URL in gmail App.

You have to use StartExistingApplication keyword and provide the gmail app bundle id.

Thanks

Faces the same issue . how to configure my email at application level ? Please explain

1 Like

new File(“C:\smtp.properties” what will be path for my system and how to locate that ?

1 Like

Am new at katalon.
How do I write mailbox as global variables.
What value should I type?

@Hari I am using Katalon studio 7.1
Getting below error on accessing your keyword: com.testwithhari.katalon.plugins.Gmail.readLatestEMailBodyContent

Error:
org.codehaus.groovy.runtime.InvokerInvocationException: com.sun.mail.util.MailConnectException: Couldn’t connect to host, port: imap.gmail.com, 993; timeout -1;
nested exception is:
java.net.ConnectException: Connection timed out: connect
at com.testwithhari.katalon.plugins.Gmail.invokeMethod(Gmail.groovy)

@Hari I tried using your plugin and it is working for forwarded email (like in your youtube tutorial) and text only email but when I try to send an activation email directly to my gmail account and run the keyword, this is the error I encountered

image