Lotus Notes Java API. Mail forwarding - java

I would like to forward emails from my Lotus Notes inbox to my gmail account.
Lotus Notes rules and agents are disabled on our server, so I developed external application for that.
I am using document.send method and mail successfully arrives to my gmail box.
The only problem is that often the email also duplicated in my Lotus Notes inbox.
I just found that the reason of that is "CC" and "BCC" fields, which I don't clean up,
however, I am looking for the way to forward email as it is - which means keep original CC and BCC and TO fields - exactly on the same way as it is done by forwarding agent.
I am using "IBM Notes 9" on Windows 7 64 bit.
I've prepared a code sample that demonstrates what I am doing.
package com.example;
import lotus.domino.*;
public class TestMailForwarder {
public static void main(String[] args) throws NotesException {
NotesThread.sinitThread();
try {
Session notesSession = NotesFactory.createSession(
(String) null, (String) null, Consts.NOTES_PASSWORD);
DbDirectory dir = notesSession.getDbDirectory(Consts.NOTES_SERVER);
Database mailDb = dir.openDatabaseByReplicaID(Consts.MAILDB_REPLICA_ID);
forwardAllEmails(mailDb);
} finally {
NotesThread.stermThread();
}
}
private static void forwardAllEmails(Database mailDb) throws NotesException {
View inbox = mailDb.getView("$Inbox");
//noinspection LoopStatementThatDoesntLoop
for (Document document = inbox.getFirstDocument();
null != document;
document = inbox.getNextDocument(document)) {
document.send(Consts.GMAIL_ADDRESS);
break;
}
}
}

Instead of trying to send the messages to your GMail, why not upload them using Gmail's IMAP interface. You would require to get the message as MIME content - which probably they are already for external incoming eMails and then push them to GMail.
I don't have a ready code sample, just one for the opposite pulling GMail into Notes, but you should be able to use that as a starting point.
A code sample for the MIME conversion is in an IBM Technote.
Hope that helps

You can't do a transparent forward with code running at the client level. Pure SMTP systems do it by preserving the RFC-822 header content while altering the RFC-821 RCPT TO data. Domino does not give client-level code independent control over these. It just uses the SendTo, CopyTo, and BlindCopyTo items. (There are some tricks that mail management and archiving vendors play in order to do things like this, but they require special changes to the Domino server's router configuration, and software on the other end as well.
Another way of accomplishing this (in response to the question you asked in your comment) would be to have your Java code make a direct connection to the gmail SMTP servers. I'm not sure how easy it is. A comment on this question states that the Java Mail API allows you to control the RCPT TO separately from the RFC822 headers, but I've not looked into the specifics other than taking note that there's an SMTPTransport class -- which is where I'd look for anything related to RFC-821 protocol. The bigger issue is that you will have to take control of converting messages into MIME format. With Notes mail, you may have a mix of Notes rich text and MIME. Theres a convertToMIME method in Notes 8.5.1 and above, but this will only convert the message body. You'll have to deal with any header content separately. (I'm not really up to speed on Notes 9, but AFAIK even though there is functionality in the client to create a .EML file when you drag a message to the desktop, there's no API there to do that for you.)

Finally, I've found a ready solution: AWESYNC.MAIL.
It is a commercial software but it does exactly what I need.

Related

Java Mail API: Callbacks

Context:
I am working on a piece of Java code where I am reading mails from an array (which works fine). I was wondering if someone can help me with the callback in order to show a fancy message like Your email was sent.
Questions:
How do I implement this?
Is there any way to get any Boolean type return value from javax.mail to check if the message was sent or not?
Maybe I should create a pool? If yes, how do I do that? Is there any signal to kill the pool?
Code:
// addressTo is the array.
Transport t = sesion.getTransport(this.beanMail.getProtocolo());
t.connect(this.beanMail.getUsuario(), this.beanMail.getPassword());
t.sendMessage(mensaje, addressTo);
t.close();
Quoting from the JavaMail API FAQ (in the context of tracking bounced messages):
While there is an Internet standard for reporting such errors (the multipart/report MIME type, see RFC1892), it is not widely implemented yet. RFC1211 discusses this problem in depth, including numerous examples.In Internet email, the existence of a particular mailbox or user name can only be determined by the ultimate server that would deliver the message. The message may pass through several relay servers (that are not able to detect the error) before reaching the end server. Typically, when the end server detects such an error, it will return a message indicating the reason for the failure to the sender of the original message. There are many Internet standards covering such Delivery Status Notifications but a large number of servers don't support these new standards, instead using ad hoc techniques for returning such failure messages. This makes it very difficult to correlate a "bounced" message with the original message that caused the problem. (Note that this problem is completely independent of JavaMail.)
Source

How to capture "send mail" in plugin for IBM Lotus notes

Here is what I am trying to do:
Add a special button to attach files to Notes "New message" window. If files were attached using this button, when email sent, they should be uploaded to the server and link to them added to the email.
My question - is it possible (and how) to capture "send mail" event in the plugin for Lotus Notus?
I don't know how an Eclipse plugin would do this. Furthermore, since Notes can be used off-line -- when it would be impossible to upload files to a server -- it would be better to have code running on the Domino server intercept the mail messages and perform the upload.
Most products that hook mail operations on the server use the Lotus Notes C API's Extension Manager functions to hook the EM_BEFORE notification for the EM_NSFNOTEUPDATE event and check whether the NSFNoteUpdate operation occurred within the server's mail.box files, and then check whether the the message requires special processing (i.e., in your case that would be by looking for a special NotesItem that your button code has inserted into the message). The usual coding method for this is to immediately change the status of the message to put it on hold, preventing the Domino router from attempting to send the message while your code is still working on it. Many products actually have two components - the EM hook DLL and a separate server task that receives a signal from the hook DLL, processes the message, and then releases it from on hold status. This approach keeps your code from tying up router threads while processing large files.
(Note: Newer versions of the Domino server have the ability to use OSGI plugins written in Java instead of using the Notes C API for operations like this. I've not looked into the details of how this might work for operations that process mail messages. )
I sort of figured it out. There is a very nice extension point provided in 8.5 - "com.ibm.notes.mailsend.MailSendAttachmentsDialog", that is specifically exists for custom handling of attachments. You can see it in plugin.xml, in IBM\Lotus\Notes\framework\shared\eclipse\plugins\com.ibm.notes.mailsend_8.5.*.jar.
The only problem is - it handles just attachments and does not have access to anything else. So if somebody figured how to get subject line and the message text from there, please reply.
Update: got it.
NotesUIElement elem = (new NotesUIWorkspace()).getCurrentElement();
if (elem instanceof NotesUIDocument) {
NotesUIDocument doc = ((NotesUIDocument) elem);
String to = doc.getField("EnterSendTo").getText();
String cc = doc.getField("EnterCopyTo").getText();
String bcc = doc.getField("EnterBlindCopyTo").getText();
String subject = doc.getField("Subject").getText();
String body = doc.getField("Body").getText();
....
}

mailto URI truncated between Java.Desktop and Windows/MS outlook

I'm trying to create an automated error reporting tool for our Java desktop app. the idea is to make it as easy as possible for customers to send us error reports whenever our application crashes.
Using the Desktop.mail API, I am able to craft messages that can be easily edited and sent from our users, but I'm running into system limitations on several platforms (notably Windows 7 and MS Outlook, which most customers are using)
When I run the example code below, you'll notice that the email message that is displayed truncates the included stack trace. I believe this has something to do with a maximum length of either command lines or URIs in the underlying systems.
Is there a better way to craft an email from an error report that is not subject to this limitation?
import java.awt.Desktop;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.net.URI;
import java.net.URLEncoder;
public class Scratchpad {
public static void main(String[] args) throws Exception {
try {
generateLongStackTrace();
} catch (Error e) {
URI uri = createMailURI(e);
// this will correctly pop up the system email client, but it will truncate the message
// after about 2K of data (this seems system dependent)
Desktop.getDesktop().mail(uri);
}
}
// Will eventually generate a really long stack overflow error
public static void generateLongStackTrace() throws Exception {
generateLongStackTrace();
}
public static URI createMailURI(Error e) throws Exception {
StringBuilder builder = new StringBuilder();
builder.append("mailto:foo#example.com?body=");
// encodes the stack trace in a mailto URI friendly form
String encodedStackTrace = URLEncoder.encode(dumpToString(e), "utf-8").replace("+", "%20");
builder.append(encodedStackTrace);
return new URI(builder.toString());
}
// Dumps the offending stack trace into a string object.
public static String dumpToString(Error e) {
StringWriter sWriter = new StringWriter();
PrintWriter writer = new PrintWriter(sWriter);
e.printStackTrace(writer);
writer.flush();
return sWriter.toString();
}
}
there are length limitations wrt admissible urls in ie and the length of a windows command line (see here, here, here and here) - i seems you run into one of these (though i admit that i have not rigorously checked).
however i think it's a plausible assumption that even if you could worm your way around the said limits the length of a generic transmission buffer between desktop applications (unless you use a dedicated api for remote controlling the target app) will be restricted somehow without a loophole.
therefore i'd suggest one of the following strategies:
distribution through a web server.
upload the data to be mailed to a web server instead using the html form file upload technique.
basically you have to forge a POST request a payload with content type set to 'multipart/form-data'. your content will need some wrapper data to conform syntactically with this mime type.
the actual transmission can be instigated by means of the WinHttpRequest COM object under windows or the curl command line program from everywhere else.
server side processing can be delegated to a suitable cgi handler which eg. might produce a (short) link to download the data fom the web server.
this link may be part of the http response to the upload request or you generate it client-side in the proper format for publishing it on the web server unaltered.
pro:
this scheme is feasible - i have repeatedly applied it in enterprise projects. data transmission can be secured through https.
con:
requires a web server to implement
send a mail using an attachment (for some details see here):
save the body of your message to some file on the desktop.
generate a mailto-link that references an attachment (instead of the bulk of your body)
any decent mail client will be able to show the attachment inline if it has some elementary mime type like 'text/plain'.
on windows platforms you set it by choosing the proper file extension ('.txt')
pro:
simple
con:
file system access on the client platform;
untested (at least by me)
good luck !

How to track an email in Java?

How I can track an email?
I' m using java on the server side for sending emails. I want to track whether it is delivered , opened, etc... How I can do that ?
This is not a Java specific issue.
You can create an HTML email, and embed an invisible gif which will report back to your server. Some software like Outlook and some web mail programs will block this for untrusted emails.
You can request a return receipt. Many mail programs ignore this entirely, and the ones which don't usually ask the user if they want to send it.
Example:
email.AddHeaderField("Disposition-Notification-To","<g.revolution#stackoverflow.com>")
There is no way to ensure that you always get the delivery or open-message notification.
Mailservers may accept the mail and drop it afterwards.
users may read the mail but dismiss the notification.
"Webbugs" (aka images in the html source of the mail that include a special token that allows the mail to be recognized) don't work in most email programs.
As a matter of fact it's very unlikely that you can see that someone got the message.
What you could do is to keep the message on your server and only send a link. If the user clicks that you can be pretty sure that he got the message. But thankfully many users would not click on such links because it's used in fraud and spam.
I suppose you're sending it through SMTP. Whenever your mail is sent to your SMTP server, your java program has no control of it:
1) If you want to know if your mail has been delivered, you should contact your SMTP server somehow (if the SMTP server is outside your control then forget that) and see if your mail has been sent.
2) You can't know if a mail has been opened by its receiver. The maximum you can do is set a flag that the mail requires acknowledgement, but that depends if the user explicitly wants to send that acknowledgment. Other possibility is set some link to your site within the mail that should be clicked to see the content. You will be able to track if the user clicked that link.
what you can do is -
you have to embed an invisible image in the body in which the src will call the page in server and log that event, you can only do it in HTML encoding.
example -
<img src="ImageServer.aspx?imageID=track.jpg& custID=134ghxx34343ai& campID=32434"/>
and then in ImageServer.aspx there will a handling code which will log that event or save it to database.
example -
private void Page_Load(object sender, System.EventArgs e)
{
// content type should be resolved programmatically
Response.ContentType = "image/jpeg";
if (!IsPostBack) Track();
Response.WriteFile(GetImageFileByID());
}
In case you send HTML email, you could add a 1x1 pixel image with some tracking parameters, that calls back to your webserver. It's not 100% reliable since some email clients (and users) block images in emails.
You can add something like
<span style="display:none">Tracking no: ${TRACK_NO}</span>
to the body of the email. This should always be in the response unless the email client strips it out.

Can a web service return a stream?

I've been writing a little application that will let people upload & download files to me. I've added a web service to this applciation to provide the upload/download functionality that way but I'm not too sure on how well my implementation is going to cope with large files.
At the moment the definitions of the upload & download methods look like this (written using Apache CXF):
boolean uploadFile(#WebParam(name = "username") String username,
#WebParam(name = "password") String password,
#WebParam(name = "filename") String filename,
#WebParam(name = "fileContents") byte[] fileContents)
throws UploadException, LoginException;
byte[] downloadFile(#WebParam(name = "username") String username,
#WebParam(name = "password") String password,
#WebParam(name = "filename") String filename) throws DownloadException,
LoginException;
So the file gets uploaded and downloaded as a byte array. But if I have a file of some stupid size (e.g. 1GB) surely this will try and put all that information into memory and crash my service.
So my question is - is it possible to return some kind of stream instead? I would imagine this isn't going to be terribly OS independent though. Although I know the theory behind web services, the practical side is something that I still need to pick up a bit of information on.
Cheers for any input,
Lee
Yes, it is possible with Metro. See the Large Attachments example, which looks like it does what you want.
JAX-WS RI provides support for sending and receiving large attachments in a streaming fashion.
Use MTOM and DataHandler in the programming model.
Cast the DataHandler to StreamingDataHandler and use its methods.
Make sure you call StreamingDataHandler.close() and also close the StreamingDataHandler.readOnce() stream.
Enable HTTP chunking on the client-side.
Stephen Denne has a Metro implementation that satisfies your requirement. My answer is provided below after a short explination as to why that is the case.
Most Web Service implementations that are built using HTTP as the message protocol are REST compliant, in that they only allow simple send-receive patterns and nothing more. This greatly improves interoperability, as all the various platforms can understand this simple architecture (for instance a Java web service talking to a .NET web service).
If you want to maintain this you could provide chunking.
boolean uploadFile(String username, String password, String fileName, int currentChunk, int totalChunks, byte[] chunk);
This would require some footwork in cases where you don't get the chunks in the right order (Or you can just require the chunks come in the right order), but it would probably be pretty easy to implement.
When you use a standardized web service the sender and reciever do rely on the integrity of the XML data send from the one to the other. This means that a web service request and answer only are complete when the last tag was sent. Having this in mind, a web service cannot be treated as a stream.
This is logical because standardized web services do rely on the http-protocol. That one is "stateless", will say it works like "open connection ... send request ... receive data ... close request". The connection will be closed at the end, anyway. So something like streaming is not intended to be used here. Or he layers above http (like web services).
So sorry, but as far as I can see there is no possibility for streaming in web services. Even worse: depending on the implementation/configuration of a web service, byte[] - data may be translated to Base64 and not the CDATA-tag and the request might get even more bloated.
P.S.: Yup, as others wrote, "chuinking" is possible. But this is no streaming as such ;-) - anyway, it may help you.
I hate to break it to those of you who think a streaming web service is not possible, but in reality, all http requests are stream based. Every browser doing a GET to a web site is stream based. Every call to a web service is stream based. Yes, all. We don't notice this at the level where we are implementing services or pages because lower levels of the architecture are dealing with this for you - but it is being done.
Have you ever noticed in a browser that sometimes it can take a while to fetch a page - the browser just keeps cranking away showing the hourglass? That is because the browser is waiting on a stream.
Streams are the reason mime/types have to be sent before the actual data - it's all just a byte stream to the browser, it wouldn't be able to identify a photo if you didn't tell it what it was first. It's also why you have to pass the size of a binary before sending - the browser won't be able to tell where the image stops and the page picks up again.
It's all just a stream of bytes to the client. If you want to prove this for yourself, just get a hold of the output stream at any point in the processing of a request and close() it. You will blow up everything. The browser will immediately stop showing the hourglass, and will display a "cannot find" or "connection reset at server" or some other such message.
That a lot of people don't know that all of this stuff is stream based shows just how much stuff has been layered on top of it. Some would say too much stuff - I am one of those.
Good luck and happy development - relax those shoulders!
For WCF I think its possible to define a member on a message as stream and set the binding appropriately - I've seen this work with wcf talking to Java web service.
You need to set the transferMode="StreamedResponse" in the httpTransport configuration and use mtomMessageEncoding (need to use a custom binding section in the config).
I think one limitation is that you can only have a single message body member if you want to stream (which kind of makes sense).
Apache CXF supports sending and receiving streams.
One way to do it is to add a uploadFileChunk(byte[] chunkData, int size, int offset, int totalSize) method (or something like that) that uploads parts of the file and the servers writes it the to disk.
Keep in mind that a web service request basically boils down to a single HTTP POST.
If you look at the output of a .ASMX file in .NET , it shows you exactly what the POST request and response will look like.
Chunking, as mentioned by #Guvante, is going to be the closest thing to what you want.
I suppose you could implement your own web client code to handle the TCP/IP and stream things into your application, but that would be complex to say the least.
I think using a simple servlet for this task would be a much easier approach, or is there any reason you can not use a servlet?
For instance you could use the Commons open source library.
The RMIIO library for Java provides for handing a RemoteInputStream across RMI - we only needed RMI, though you should be able to adapt the code to work over other types of RMI . This may be of help to you - especially if you can have a small application on the user side. The library was developed with the express purpose of being able to limit the size of the data pushed to the server to avoid exactly the type of situation you describe - effectively a DOS attack by filling up ram or disk.
With the RMIIO library, the server side gets to decide how much data it is willing to pull, where with HTTP PUT and POSTs, the client gets to make that decision, including the rate at which it pushes.
Yes, a webservice can do streaming. I created a webservice using Apache Axis2 and MTOM to support rendering PDF documents from XML. Since the resulting files could be quite large, streaming was important because we didn't want to keep it all in memory. Take a look at Oracle's documentation on streaming SOAP attachments.
Alternately, you can do it yourself, and tomcat will create the Chunked headers. This is an example of a spring controller function that streams.
#RequestMapping(value = "/stream")
public void hellostreamer(HttpServletRequest request, HttpServletResponse response) throws CopyStreamException, IOException
{
response.setContentType("text/xml");
OutputStreamWriter writer = new OutputStreamWriter (response.getOutputStream());
writer.write("this is streaming");
writer.close();
}
It's actually not that hard to "handle the TCP/IP and stream things into your application". Try this...
class MyServlet extends HttpServlet
{
public void doGet(HttpServletRequest request, HttpServletResponse response)
{
response.getOutputStream().println("Hello World!");
}
}
And that is all there is to it. You have, in the above code, responded to an HTTP GET request sent from a browser, and returned to that browser the text "Hello World!".
Keep in mind that "Hello World!" is not valid HTML, so you may end up with an error on the browser, but that really is all there is to it.
Good Luck in your development!
Rodney

Categories