Parse IMAP message and extract header information - parsing

I am trying to extract header and body information from email, the following code retrieves the header and body in their raw form. I have an email object that contains the fields from, subject, date, and body. I would like to extract these values from the email and assign them to the email object. How do I get around it? I have tried several ways like getting the header info and using a streamReader.ReadLine() to get a line but I got illegal path exceptions. I know I can use a library but I need to achieve it this way.
What I mean is this, IMAP command returns header information. And I want to extract subject value, date value, sender e-amil, etc. and assign them to my email objects corresponding values like
emailObject.subject = "subjectValue"
public class Imap
{
static void Main(string[] args)
{
try
{
path = Environment.CurrentDirectory + "\\emailresponse.txt";
if (System.IO.File.Exists(path))
System.IO.File.Delete(path);
sw = new System.IO.StreamWriter(System.IO.File.Create(path));
tcpc = new System.Net.Sockets.TcpClient("imap.gmail.com", 993);
ssl = new System.Net.Security.SslStream(tcpc.GetStream());
ssl.AuthenticateAsClient("imap.gmail.com");
receiveResponse("");
Console.WriteLine("username : ");
username = Console.ReadLine();
Console.WriteLine("password : ");
password = Console.ReadLine();
receiveResponse("$ LOGIN " + username + " " + password + " \r\n");
Console.Clear();
receiveResponse("$ LIST " + "\"\"" + " \"*\"" + "\r\n");
receiveResponse("$ SELECT INBOX\r\n");
receiveResponse("$ STATUS INBOX (MESSAGES)\r\n");
Console.WriteLine("enter the email number to fetch :");
int number = int.Parse(Console.ReadLine());
Console.WriteLine("*************Header************");
Console.WriteLine("");
// receiveResponse("$ FETCH " + number + " body[header]\r\n");
// BODY.PEEK[HEADER.FIELDS (SUBJECT)]
// StringBuilder sb = receiveResponse("$ FETCH " + number + " BODY.PEEK[HEADER.FIELDS (From Subject Date)]\r\n");
StringBuilder sb= receiveResponse("$ FETCH " + number + " body.peek[header]\r\n");
Console.WriteLine(sb);
Console.WriteLine("");
Console.WriteLine("Body");
sb = new StringBuilder();
sb=receiveResponse("$ FETCH " + number + " body[text]\r\n");
System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding();
byte[] serverbuff = new Byte[1024];
int count = 0;
string retval = enc.GetString(serverbuff, 0, count);
Console.WriteLine(sb.ToString());
receiveResponse("$ LOGOUT\r\n");
}
catch (Exception ex)
{
Console.WriteLine("error: " + ex.Message);
}
finally
{
if (sw != null)
{
sw.Close();
sw.Dispose();
}
if (ssl != null)
{
ssl.Close();
ssl.Dispose();
}
if (tcpc != null)
{
tcpc.Close();
}
}
Console.ReadKey();
}
static StringBuilder receiveResponse(string command)
{
sb = new StringBuilder();
try
{
if (command != "")
{
if (tcpc.Connected)
{
dummy = Encoding.ASCII.GetBytes(command);
ssl.Write(dummy, 0, dummy.Length);
}
else
{
throw new ApplicationException("TCP CONNECTION DISCONNECTED");
}
}
ssl.Flush();
buffer = new byte[2048];
bytes = ssl.Read(buffer, 0, 2048);
sb.Append(Encoding.ASCII.GetString(buffer));
// Console.WriteLine(sb.ToString());
sw.WriteLine(sb.ToString());
// sb = new StringBuilder();
return sb;
}
catch (Exception ex)
{
throw new ApplicationException(ex.Message);
}
}

You said you do not want to use an IMAP library. This means that you will have to implement your own. You should start by reading RFC 3501 because there is no chance you could get the protocol right without reading the docs carefuly. In particular, you're issuing a STATUS command on the currently selected mailbox, which is explicitly forbidden by the protocol specification. The rest of the code supports the assumption that you have not read the RFC yet.

Related

JavaMail MIME attachment link by cid

Background
I have banged my head against this for a while and not made much progress. I am generating MPEG_4 / AAC files in Android and sending them by email as .mp3 files. I know they aren't actually .mp3 files, but that allows Hotmail and Gmail to play them in Preview. They don't work on iPhone though, unless they are sent as .m4a files instead which breaks the Outlook / Gmail Preview.
So I have thought of a different approach which is to attach as a .mp3 file but have an HTML link in the email body which allows the attached file to be downloaded and specifies a .m4a file name. Gmail / Outlook users can click the attachment directly whereas iPhone users can use the HTML link.
Issue
I can send an email using JavaMail with HTML in it including a link which should be pointing at the attached file to allow download of that file by the link. Clicking on the link in Gmail (Chrome on PC) gives a 404 page and iPhone just ignores my clicking on the link.
Below is the code in which I generate a multipart message and assign a CID to the attachment which I then try to access using the link in the html part. It feels like I am close, but maybe that is an illusion. I'd be massively grateful if someone could help me fix it or save me the pain if it isn't possible.
private int send_email_temp(){
Properties props = new Properties();
props.put("mail.smtp.auth", "true");
props.put("mail.smtp.host", smtp_host_setting);
//props.put("mail.debug", "true");
props.put("mail.smtp.ssl.enable", "true");
props.put("mail.smtp.starttls.enable", "true");
props.put("mail.smtp.port", smtp_port_setting);
session = Session.getInstance(props);
ActuallySendAsync_temp asy = new ActuallySendAsync_temp(true);
asy.execute();
return 0;
}
class ActuallySendAsync_temp extends AsyncTask<String, String, Void> {
public ActuallySendAsync_temp(boolean boo) {
// something to do before sending email
}
#Override
protected Void doInBackground(String... params) {
try {
Message message = new MimeMessage(session);
message.setFrom(new InternetAddress(username));
message.setRecipients(Message.RecipientType.TO,
InternetAddress.parse(recipient_email_address));
message.setSubject(email_subject);
Multipart multipart = new MimeMultipart();
MimeBodyPart messageBodyPart = new MimeBodyPart();
String file = mFileName;
/**/
DataSource source = new FileDataSource(file);
messageBodyPart.setDataHandler(new DataHandler(source));
/* /
File ff = new File(file);
try {
messageBodyPart.attachFile(ff);
} catch(IOException eio) {
Log.e("Message Error", "Old Macdonald");
}
/* /
messageBodyPart = new PreencodedMimeBodyPart("base64");
byte[] file_bytes = null;
File ff = new File(file);
try {
int length = (int) ff.length();
BufferedInputStream reader = new BufferedInputStream(new FileInputStream(ff));
file_bytes = new byte[length];
reader.read(file_bytes, 0, length);
reader.close();
} catch (IOException eio) {
Log.e("Message Error", "Old Macdonald");
}
messageBodyPart.setText(Base64.encodeToString(file_bytes, Base64.DEFAULT));
messageBodyPart.setHeader("Content-Transfer-Encoding", "base64");
/**/
messageBodyPart.setFileName( DEFAULT_AUDIO_FILENAME );//"AudioClip.mp3");
//messageBodyPart.setContentID("<audio_clip>");
String content_id = UUID.randomUUID().toString();
messageBodyPart.setContentID("<" + content_id + ">");
messageBodyPart.setDisposition(Part.ATTACHMENT);//INLINE);
messageBodyPart.setHeader("Content-Type", "audio/mp4");
multipart.addBodyPart(messageBodyPart);
MimeBodyPart messageBodyText = new MimeBodyPart();
//final String MY_HTML_MESSAGE = "<h1>My HTML</h1><a download=\"AudioClip.m4a\" href=\"cid:audio_clip\">iPhone Download</a>";
final String MY_HTML_MESSAGE = "<h1>My HTML</h1><a download=\"AudioClip.m4a\" href=\"cid:" + content_id + "\">iPhone Download</a>";
messageBodyText.setContent( MY_HTML_MESSAGE, "text/html");
multipart.addBodyPart(messageBodyText);
message.setContent(multipart);
Print_Message_To_Console(message);
Transport transport = session.getTransport("smtp");
transport.connect(smtp_host_setting, username, password);
transport.sendMessage(message, message.getAllRecipients());
transport.close();
} catch (MessagingException e) {
e.printStackTrace();
} finally {
}
return null;
}
#Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
// something to do after sending email
}
}
int Print_Message_To_Console(Message msg) {
int ret_val = 0;
int line_num = 0;
InputStream in = null;
InputStreamReader inputStreamReader = null;
BufferedReader buff_reader = null;
try {
in = msg.getInputStream();
inputStreamReader = new InputStreamReader(in);
buff_reader = new BufferedReader(inputStreamReader);
String temp = "";
while ((temp = buff_reader.readLine()) != null) {
Log.d("Message Line " + Integer.toString(line_num++), temp);
}
} catch(Exception e) {
Log.d("Message Lines", "------------ OOPS! ------------");
ret_val = 1;
} finally {
try {
if (buff_reader != null) buff_reader.close();
if (inputStreamReader != null) inputStreamReader.close();
if (in != null) in.close();
} catch(Exception e2) {
Log.d("Message Lines", "----------- OOPS! 2 -----------");
ret_val = 2;
}
}
return ret_val;
}
You need to create a multipart/related and set the main text part as the first body part.

WSO2 Identity Server - Oauth 2.0 - Sign-off Example for Java

I wrote a Java based sign-off routine (token revocation) for an Oauth2 authentication flow. See below the code implementation following the cURL protocol instructions in the manual described [ here ]. The program code compiles and works without error message, but after the log-off the user accounts still remains in a connected state under the WSO2 dashboard query.
See below the Servlet class that triggers the log-off function:
class SignoffServlet extends HttpServlet {
#Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException,IOException {
try{
String accessToken = (String) req.getSession().getAttribute("access_token");
System.out.println("Start Logoff processing for revoke of the token: " + accessToken);
URL url = new URL (Oauth2Server + "/oauth2/revoke?token="+accessToken);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
// new encode with Apache codec (for Java8 use native lib)
String userCredentials = clientId + ":" + clientSecret;
String basicAuth = "Basic " + new String(new Base64().encode(userCredentials.getBytes()));
connection.setRequestProperty ("Authorization", basicAuth);
connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded;charset=UTF-8");
connection.addRequestProperty("token", accessToken);
connection.addRequestProperty("token_type_hint", "access_token");
//connection.setRequestProperty("token", accessToken);
// connection.setRequestProperty("token_type_hint", "access_token");
connection.setRequestMethod("POST");
connection.setDoOutput(true);
InputStream content = (InputStream)connection.getInputStream();
BufferedReader in =
new BufferedReader (new InputStreamReader (content));
String line;
while ((line = in.readLine()) != null) {
System.out.println(line);
System.out.println("Logoff finished sucessfully");
}
} catch(Exception e) {
System.out.println("Logoff failed, error cause: " + e.toString());
e.printStackTrace();
}
System.out.println("Logoff finished sucessfully");
// return the json of the user's basic info
String html_header = "<html><body>";
String myjson = "<br>Logoff completed sucessfully";
myjson += "<br><br><b><a href='./index.html'>Back to login page</a></b><br>";
String html_footer = "</body></html>";
String mypage = html_header + myjson + html_footer;
resp.setContentType("text/html");
resp.getWriter().println(myjson);
}
}
Advice about what to change in the Java code to activate the sign-off function for Oauth 2.0 is welcome.
Thanks for detailed explanations about the difference between authorization and authentication in Oauth2. See below the code that is able to revoke the valid Oauth2 token:
class SignoffServlet extends HttpServlet {
#Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException,IOException {
String outputl = "";
try{
String accessToken = (String) req.getSession().getAttribute("access_token");
// testing .. inhibu acivate this line: // revoke accessToken = "abc";
System.out.println("Start Logoff processing for revoke of the token: " + accessToken);
// URL url = new URL (Oauth2Server + "/oauth2/revoke?token="+accessToken);
// URL url = new URL (Oauth2Server + "/oauth2endpoints/revoke");
URL url = new URL (Oauth2Server + "/oauth2/revoke");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded;charset=UTF-8");
// new encode with Apache codec (for Java8 use native lib)
String userCredentials = clientId + ":" + clientSecret;
String basicAuth = "Basic " + new String(new Base64().encode(userCredentials.getBytes()));
basicAuth = basicAuth.replace("\\r", "");
basicAuth = basicAuth.replace("\\n", "");
connection.setRequestProperty ("Authorization", basicAuth);
connection.setUseCaches(false);
connection.setDoInput(true);
connection.setDoOutput(true);
// send data
// String str = "{\"token\": \"" + accessToken + "\",\"token_type_hint\":\"access_token\"}";
// example of JSON string "{\"x\": \"val1\",\"y\":\"val2\"}";
//byte[] outputInBytes = str.getBytes("UTF-8");
//OutputStream os = connection.getOutputStream();
//os.write( outputInBytes );
// os.close();
//send request
DataOutputStream wr = new DataOutputStream(connection.getOutputStream());
wr.writeBytes("token=" + accessToken);
wr.flush();
wr.close();
// end of new method
InputStream content = (InputStream)connection.getInputStream();
BufferedReader in =
new BufferedReader (new InputStreamReader (content));
String line;
while ((line = in.readLine()) != null) {
// System.out.println(line); // for debug only
outputl += line;
}
} catch(Exception e) {
System.out.println("Logoff failed, error cause: " + e.toString());
e.printStackTrace();
}
System.out.println("Logoff finished successfully");
// return the json of the user's basic info
// customized Apache HTTP GET with header - Claude, 27 August 2015 reading user information
// ===============================================================================================
String tokeninfo = "";
String infourl = Oauth2Server + "/oauth2/userinfo?schema=openid";
StringBuilder infobody = new StringBuilder();
DefaultHttpClient infohttpclient = new DefaultHttpClient(); // create new httpClient
HttpGet infohttpGet = new HttpGet(infourl); // create new httpGet object
// get some info about the user with the access token
String currentToken = (String) req.getSession().getAttribute("access_token");
String bearer = "Bearer " + currentToken.toString();
infohttpGet.setHeader("Authorization", bearer);
try {
HttpResponse response = infohttpclient.execute(infohttpGet); // execute httpGet
StatusLine statusLine = response.getStatusLine();
int statusCode = statusLine.getStatusCode();
if (statusCode == HttpStatus.SC_OK) {
System.out.println(statusLine);
infobody.append(statusLine + "\n");
HttpEntity e = response.getEntity();
String entity = EntityUtils.toString(e);
infobody.append(entity);
} else {
infobody.append(statusLine + "\n");
// System.out.println(statusLine);
}
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
tokeninfo = infobody.toString();
infohttpGet.releaseConnection(); // stop connection
}
// User info lookup is done fetching current log status of the token
if (tokeninfo.startsWith("HTTP/1.1 400 Bad Request")) {
tokeninfo = "Token " + currentToken + " was revoked";
};
String html_header = "<html><body>";
String myjson = "<br>Logoff completed successfully";
myjson += "<br>Current Userinfo and Token Status";
myjson += "<br>" + tokeninfo + "<br>";
myjson += "<br><br><b><a href='./index.html'>Back to login page</a></b><br>";
String html_footer = "</body></html>";
String mypage = html_header + myjson + html_footer;
resp.setContentType("text/html");
resp.getWriter().println(myjson);
// to print signoff screen for debug purpose
// resp.getWriter().println(outputl);
}
}
Above doc has been mentioned the way to revoke the access token.Access token revoking and sign-off from OAuth2 authorization server are two different process. As an example; in Facebook, you can revoke the access token which are given for different applications. But it does not mean that you are sign-off from FB or any other application which you already login.
OAuth2 is not an authentication mechanism. It is authorization framework. It does not contain standard way to sign-off from authorization sever. However, there is some custom way which you can use to sign-off (terminate the SSO session in WSO2IS) from WSO2IS which can be used. But, it must be done using the end user's browser (not using the back channel) by calling following url. Please check last part of this for more details
https://localhost:9443/commonauth?commonAuthLogout=true&type=oidc2&sessionDataKey=7fa50562-2d0f-4234-8e39-8a7271b9b273&commonAuthCallerPath=http://localhost:8080/openidconnect/oauth2client&relyingParty=OpenidConnectWebapp

status.getText() does not give proper HTML

I am using java and twitter4j.
Issue : I do not get proper response from status.getText() method, link references comes as text
I have a problem. My method is as follow:
Twitter twitter = null;
String userName = "clientname";
int numberOfTweets = 0;
StringBuilder timeLineText = new StringBuilder();
try {
twitter = new TwitterFactory(new GetAuthenticConfiguration().getConfigObject()).getInstance();
ResponseList<Status> statuses = twitter.getUserTimeline(userName);
timeLineText.append("<li>");
for (Status status : statuses) {
numberOfTweets++;
if (numberOfTweets > 12) {
break;
}
int remainder = numberOfTweets % 3;
if (remainder == 0) {
timeLineText.append("</li><li>");
} else {
StringBuilder tempText = new StringBuilder();
try {
tempText.append("<p>");
tempText.append("<span>");
tempText.append("<img alt=\"" + status.getUser().getScreenName() + "\" src=\"" + status.getUser().getMiniProfileImageURL() + "\" />");
tempText.append("<b>" + status.getUser().getName() + "</b> #" + status.getUser().getScreenName() + " " + new SimpleDateFormat("dd MMM").format(status.getCreatedAt()));
tempText.append("</span>");
tempText.append("<p>" + status.getText() + "</p>");
tempText.append("</p>");
} catch (Exception e) {
System.out.println(e);
}
timeLineText.append(tempText);
}
}
timeLineText.append("</li>");
} catch (Exception te) {
System.out.println(te);
}
The response i get is :
Can you tell us which Rolls-Royce #engine powers this aircraft? #AvGeek http://t.co/t5tNXQuMFB
instead of
Can you tell us which Rolls-Royce <a href="/hashtag/engine?src=hash" data-query-source="hashtag_click" class="twitter-hashtag pretty-link js-nav" dir="ltr" ><s>#</s><b>engine</b></a> powers this aircraft? <a href="/hashtag/AvGeek?src=hash" data-query-source="hashtag_click" class="twitter-hashtag pretty-link js-nav" dir="ltr" ><s>#</s><b>AvGeek</b></a> <a href="http://t.co/t5tNXQuMFB" class="twitter-timeline-link u-isHiddenVisually" data-pre-embedded="true" dir="ltr" >pic.twitter.com/t5tNXQuMFB</a>
The issue is I am not getting the proper html . Can anyone tell me the reason of it please?
After doing lot of R & D, I have found out that Status.getText() method gives only plain text.
We have to manually convert it to links,hashtags and users.
Below is the method I have written to do that.
Just pass your getText() output to this method (tweet).
I hope this will help to many beginners of Twitter4J.
private String linkifyTweet(String tweet) {
Pattern pattern;
Matcher matcher;
String regex_url = "((https?://\\S+)|(www.\\S+))";
String regex_hashtag = "#(\\w+)";
String regex_user = "#(\\w+)";
//regex to apply links to all urls in the tweet
pattern = Pattern.compile(regex_url);
matcher = pattern.matcher(tweet);
if (matcher.find()) {
tweet = tweet.replaceAll(regex_url, "<a target=\"_blank\" href=\"$1\">$1</a>");
}
//regex to apply links to all hashtags in the tweet
pattern = Pattern.compile(regex_hashtag);
matcher = pattern.matcher(tweet);
if (matcher.find()) {
tweet = tweet.replaceAll(regex_hashtag, "<a target=\"_blank\" href=\"https://www.twitter.com/hashtag/$1?src=hash\">#$1</a>");
}
//regex to apply links to all users in the tweet
pattern = Pattern.compile(regex_user);
matcher = pattern.matcher(tweet);
if (matcher.find()) {
tweet = tweet.replaceAll(regex_user, "<a target=\"_blank\" href=\"https://www.twitter.com/$1\">#$1</a>");
}
//System.out.println(tweet);
return tweet;
}

OleDbConnection - object reference not set to an instance of an object

I have a form an one button on it,
below is very really simple my code:
private void ConnectDb()
{
try
{
connect = new OleDbConnection();
connect.ConnectionString = #"Provider=Microsoft.ACE.OLEDB.15.0;Data Source=MySong.accdb;Persist Security Info=false;";
connect.Open();
statusText.Text = "Database connected";
command = connect.CreateCommand();
}
catch (Exception)
{
statusText.Text = "ERROR::Database failed";
}
}
private void CloseConnectDb()
{
if (connect != null)
{
connect.Close();
statusText.Text = "Database Closed";
}
}
private void btnTambah_Click(object sender, EventArgs e)
{
DateTime tanggal = DateTime.Today;
Band = txtArtis.Text;
Title = txtJudul.Text;
this.ConnectDb();
command.CommandText = "INSERT INTO TableLagu (Tanggal, Artis, Title, Status) VALUES ('" + tanggal + "', '" + Band + "', '" + Title + "', 'Belum ada')";
if (command.ExecuteNonQuery() != 0) //executenonquery returns number of row affected
{
statusText.Text = "ADD--Data Success inserted";
txtArtis.Text = "";
txtJudul.Text = "";
}
else statusText.Text = "ERROR::Insert failed";
this.CloseConnectDb();
}
When i click on my 'btnTambah' button, it always say "object reference not set to an instance of an object" and display "ERROR::Database failed" on its statusText.
any solution??
i think this code doesn't run while try to call ConnectDb method.
you can see my connection string
Provider=Microsoft.ACE.OLEDB.15.0;
actually, when i creating it, i have microsoft access database 2013 installed on my machine. it works good.
now, i'm trying to run my application on my friends computer that microsoft access installed version 2007. and got an error like above.

Display HTTP Request Information - BlackBerry

How can I get the all HTTP request headers, method, the suffix of the connection, and all parameters that I added to the request?
Try something like this (I ran this code on a background thread, which I why I use UiApplication.invokeLater() to display results):
try {
ConnectionFactory factory = new ConnectionFactory(); // for OS 5.0+
factory.setPreferredTransportTypes(new int[] {
TransportInfo.TRANSPORT_TCP_WIFI,
TransportInfo.TRANSPORT_TCP_CELLULAR
});
// For OS < 5.0
//HttpConnection conn = (HttpConnection) Connector.open("http://www.google.com;interface=wifi");
HttpConnection conn = (HttpConnection) factory.getConnection("http://www.google.com").getConnection();
conn.setRequestProperty("sessionId", "ABCDEF0123456789");
final StringBuffer results = new StringBuffer();
String key = "";
int index = 0;
// loop over all the header fields, and record their values
while (key != null) {
key = conn.getHeaderFieldKey(index);
if (key != null) {
String value = conn.getHeaderField(key);
results.append(key + " = " + value + "\n\n");
}
index++;
}
results.append("method = " + conn.getRequestMethod() + "\n\n");
// we (should) know which request properties we've set, so we ask
// for them by name here
String sessionId = conn.getRequestProperty("sessionId");
results.append("sessionId = " + sessionId + "\n\n");
String url = conn.getURL();
results.append("URL = " + url);
// show the result on screen (UI thread)
UiApplication.getUiApplication().invokeLater(new Runnable() {
public void run() {
textField.setText(results.toString());
}
});
} catch (IOException e) {
e.printStackTrace();
}

Resources