This post covers a script for sending a text email from an OOo Writer document. The script is written in Java and runs as a macro in OpenOffice.org.
Ths script puts in the mail body the selected text from the OOo Writer document or the whole document, if nothing is selected. To get the mail subject and the mail recipients from the user, the script creates a simple dialog that uses OOo's com.sun.star.awt API.
For sending a mail this script uses the JavaMail API (mail.jar from javamail-1_4_3.zip). Additionally this script uses Apache log4j (log4j-1.2.16.jar from apache-log4j-1.2.16.zip) for logging some messages.
If you need a simpler example to get started with OOo macros in Java, you should read first [Java] OOo Writer and Calc macro examples.
I've used OOo 2.3.1, NetBeans IDE 6.0, Java 1.6_04 and Windows XP to develop this example. To check, if the macro is still working I've used OOo 3.2.0, NetBeans IDE 6.8, Java 1.6_16 and Ubuntu 10.04 LTS. It might work with other versions, too. Although using older versions of Java, it might be necessary to additionally use the JavaBeans Activation Framework (activation.jar from jaf-1_1-fr). In this case the activation.jar should be deployed together with the mail.jar and added to the classpath of the parcel-descriptor.
Source code
The source code of this script consists of six Java classes:
- TextEmailSender.java is the main script
- Dialog.java creates the OOo dialog
- SmtpMailSender.java, MailSender.java, MailSenderConfiguration.java, and MailContentFactory.java are used for sending the mail
Code: Select all
package ooo.scripting.writer;
import java.io.IOException;
import java.util.Properties;
import javax.mail.MessagingException;
import org.apache.log4j.Logger;
import com.sun.star.awt.ActionEvent;
import com.sun.star.awt.KeyEvent;
import com.sun.star.awt.MouseEvent;
import com.sun.star.awt.PushButtonType;
import com.sun.star.awt.XTextComponent;
import com.sun.star.container.XIndexAccess;
import com.sun.star.lang.IndexOutOfBoundsException;
import com.sun.star.lang.WrappedTargetException;
import com.sun.star.script.provider.XScriptContext;
import com.sun.star.text.XText;
import com.sun.star.text.XTextDocument;
import com.sun.star.text.XTextRange;
import com.sun.star.uno.UnoRuntime;
import com.sun.star.uno.XComponentContext;
import com.sun.star.view.XSelectionSupplier;
import ooo.dialog.Dialog;
import util.mail.MailSender;
import util.mail.SmtpMailSender;
import util.mail.MailSenderConfiguration;
public class TextEmailSender {
/** Logger */
private static final Logger LOGGER = Logger.getLogger(TextEmailSender.class);
/** New line separator */
public static final String NEWLINE = System.getProperty("line.separator");
/** Name of the mail properties file */
private static final String MAIL_PROPERTIES = "mail.properties";
/** Max length of automatically created mail subject */
private static final int MAX_SUBJECT_LENGTH = 80;
/** OOo component context for showing a dialog */
private XComponentContext xcomponentcontext;
/** OOo Writer text document */
private XTextDocument xtextdocument;
/** Mail subject */
private String subject;
/** Mail recipients */
private String recipients;
/**
* Constructs a text email sender which uses the OOo component context and
* OOo Writer text document.
*
* @param xcomponentcontext The OOo component context
* @param xtextdocument The OOo Writer text document
*/
public TextEmailSender(XComponentContext xcomponentcontext, XTextDocument xtextdocument) {
this.xcomponentcontext = xcomponentcontext;
this.xtextdocument = xtextdocument;
this.subject = null;
this.recipients = null;
LOGGER.info("TextEmailSender constructed");
}
/**
* Returns the current selections of the text document or the whole text of
* the text document, if no text is selected.
*
* @return The current selections or the whole text of the text document
*/
private String getDocumentText() throws IndexOutOfBoundsException, WrappedTargetException {
// Get all selected regions of the document
XSelectionSupplier xSelectionSupplier = (XSelectionSupplier) UnoRuntime.queryInterface(XSelectionSupplier.class, xtextdocument.getCurrentController());
XIndexAccess xIndexAccess = (XIndexAccess) UnoRuntime.queryInterface(XIndexAccess.class, xSelectionSupplier.getSelection());
String text = null;
int count = xIndexAccess.getCount();
if (count > 0) {
// Get text inside selected regions
for (int i=0; i<count; i++) {
XTextRange xTextRange = (XTextRange) UnoRuntime.queryInterface(XTextRange.class, xIndexAccess.getByIndex(i));
text = (text == null)? "": text+NEWLINE+NEWLINE;
text += xTextRange.getString();
}
}
if (text == null || text.trim().length() == 0) {
// Get text of the document
XText xtext = xtextdocument.getText();
text = (xtext != null)? xtext.getString(): "";
}
LOGGER.info("Document text determined");
return text;
}
/**
* Returns a mail subject proposal for mailing the text.
*
* Takes the first line of the text. If the first line is longer than the
* maximum subject line, everything after the maximum subject line length
* and the last blank of that subject will be removed.
*
* @param text The text
* @return The subject proposal
*/
private String getSubjectProposal(String text) {
int maxSubjectLength = (text.indexOf(NEWLINE) > 0)? text.indexOf(NEWLINE): MAX_SUBJECT_LENGTH + 1;
String subjectProposal = text.substring(0, Math.min(text.length(), maxSubjectLength));
if (subjectProposal.length() > MAX_SUBJECT_LENGTH) {
subjectProposal = text.substring(0, MAX_SUBJECT_LENGTH);
if (subjectProposal.lastIndexOf(" ") > 0) {
subjectProposal = subjectProposal.substring(0, subjectProposal.lastIndexOf(" "));
}
}
LOGGER.info("Subject proposal determined: '"+subjectProposal+"'");
return subjectProposal;
}
/**
* Shows a dialog to initialize the subject and recipients of the mail.
*
* @param subjectProposal The subject proposal
* @param recipientsProposal The recipients proposal
*/
private void initSubjectAndRecipients(String subjectProposal, String recipientsProposal) throws Exception {
Dialog dialog = new Dialog(xcomponentcontext,100,100,80,280,"Send Mail","sendMailDialog");
dialog.insertFixedText(10, 10, 30, "Subject:");
XTextComponent subjectField = dialog.insertTextField(42, 10, 228, subjectProposal);
dialog.insertFixedText(10, 30, 30, "Recipients:");
XTextComponent recipientsField = dialog.insertTextField(42, 30, 228, recipientsProposal);
dialog.insertButton(105, 60, 30, "OK", PushButtonType.OK_value);
dialog.insertButton(145, 60, 30, "Cancel", PushButtonType.CANCEL_value);
short returnValue = dialog.execute();
if (returnValue == PushButtonType.OK_value) {
subject = (subjectField.getText().trim().length()>0)? subjectField.getText(): null;
recipients = (recipientsField.getText().trim().length()>0)? recipientsField.getText(): null;
}
dialog.dispose();
}
/**
* Sends the email.
*
* @param text The email text
*/
private void sendMail(String text) throws Exception, IOException, MessagingException {
Properties mailProperties = new Properties();
mailProperties.load(this.getClass().getClassLoader().getResourceAsStream(MAIL_PROPERTIES));
String subjectProposal = getSubjectProposal(text);
String recipientsProposal = mailProperties.getProperty("mail.recipients.proposal");
initSubjectAndRecipients(subjectProposal, recipientsProposal);
if (subject != null && recipients != null) {
MailSenderConfiguration mailSenderConfiguration = new MailSenderConfiguration();
mailSenderConfiguration.setSender(mailProperties.getProperty("mail.smtpauth.sender"));
mailSenderConfiguration.setSmtpHost(mailProperties.getProperty("mail.smtpauth.host"));
mailSenderConfiguration.setUser(mailProperties.getProperty("mail.smtpauth.user"));
mailSenderConfiguration.setPassword(mailProperties.getProperty("mail.smtpauth.password"));
mailSenderConfiguration.setSubject(subject);
mailSenderConfiguration.setRecipients(recipients);
MailSender mailSender = new SmtpMailSender(mailSenderConfiguration);
mailSender.send(text);
LOGGER.info("Email send");
}
else {
LOGGER.warn("No email send");
}
}
/**
* Gets the text from the OOo Writer text document and sends an email.
*/
public void send() {
try {
String documentText = getDocumentText();
sendMail(documentText);
} catch (Exception ex) {
String message = "Sending text email failed: "+ex.getMessage()+ex.getStackTrace();
LOGGER.error(message);
throw new RuntimeException(message,ex);
}
}
/**
* Sending text email called from a toolbar.
*
* @param xScriptContext The script context of OOo's scripting framework
* @param ignored The ignored number
*/
public static void sendTextEmail(XScriptContext xScriptContext, Short ignored) {
LOGGER.info("Sending text email called from a toolbar");
sendTextEmail(xScriptContext);
}
/**
* Sending text email called from a button with an action.
*
* @param xScriptContext The script context of OOo's scripting framework
* @param ignored The ignored action event
*/
public static void sendTextEmail(XScriptContext xScriptContext, ActionEvent ignored) {
LOGGER.info("Sending text email called from a button with an action");
sendTextEmail(xScriptContext);
}
/**
* Sending text email called from a button with a key.
*
* @param xScriptContext The script context of OOo's scripting framework
* @param ignored The ignored key event
*/
public static void sendTextEmail(XScriptContext xScriptContext, KeyEvent ignored) {
LOGGER.info("Sending text email called from a button with a key");
sendTextEmail(xScriptContext);
}
/**
* Sending text email called from a button with the mouse.
*
* @param xScriptContext The script context of OOo's scripting framework
* @param ignored The ignored mouse event
*/
public static void sendTextEmail(XScriptContext xScriptContext, MouseEvent ignored) {
LOGGER.info("Sending text email called from a button with the mouse");
sendTextEmail(xScriptContext);
}
/**
* Sending text email called from a menu or the "Run Macro..." menu.
*
* @param xScriptContext The script context of OOo's scripting framework
*/
public static void sendTextEmail(XScriptContext xScriptContext) {
LOGGER.info("Sending text email called");
XComponentContext xcomponentcontext = xScriptContext.getComponentContext();
XTextDocument xtextdocument = (XTextDocument) UnoRuntime.queryInterface(XTextDocument.class, xScriptContext.getDocument());
if (xtextdocument != null) {
TextEmailSender textEmailSender = new TextEmailSender(xcomponentcontext,xtextdocument);
textEmailSender.send();
}
}
}
Dialog.java
Code: Select all
package ooo.dialog;
import com.sun.star.awt.XButton;
import com.sun.star.awt.XControl;
import com.sun.star.awt.XControlContainer;
import com.sun.star.awt.XControlModel;
import com.sun.star.awt.XDialog;
import com.sun.star.awt.XFixedText;
import com.sun.star.awt.XTextComponent;
import com.sun.star.awt.XToolkit;
import com.sun.star.awt.XWindow;
import com.sun.star.awt.XWindowPeer;
import com.sun.star.beans.XPropertySet;
import com.sun.star.container.XNameAccess;
import com.sun.star.container.XNameContainer;
import com.sun.star.lang.XComponent;
import com.sun.star.lang.XMultiComponentFactory;
import com.sun.star.lang.XMultiServiceFactory;
import com.sun.star.uno.Exception;
import com.sun.star.uno.UnoRuntime;
import com.sun.star.uno.XComponentContext;
/**
* The source code of this class bases heavily on the OOo Developer's Guide:
* http://api.openoffice.org/docs/DevelopersGuide/GUI/GUI.xhtml#1_Graphical_User_Interfaces
*
* This class provides methods to create, execute and dispose an OOo Dialog
* with labels (fixed text), buttons, text fields, and password fields.
*/
public class Dialog {
private XComponentContext xComponentContext;
private XMultiComponentFactory xMultiComponentFactory;
private XMultiServiceFactory xMultiComponentFactoryDialogModel;
private XNameContainer xDialogModelNameContainer;
private XControl xDialogControl;
private XControlContainer xDialogContainer;
public Dialog(XComponentContext xComponentContext, int posX, int posY, int height, int width, String title, String name) throws Exception {
this.xComponentContext = xComponentContext;
init(posX, posY, height, width, title, name);
}
private void init(int posX, int posY, int height, int width, String title, String name) throws Exception {
xMultiComponentFactory = xComponentContext.getServiceManager();
Object oDialogModel = xMultiComponentFactory.createInstanceWithContext("com.sun.star.awt.UnoControlDialogModel", xComponentContext);
// The XMultiServiceFactory of the dialogmodel is needed to instantiate the controls...
xMultiComponentFactoryDialogModel = (XMultiServiceFactory) UnoRuntime.queryInterface(XMultiServiceFactory.class, oDialogModel);
// The named container is used to insert the created controls into...
xDialogModelNameContainer = (XNameContainer) UnoRuntime.queryInterface(XNameContainer.class, oDialogModel);
// create the dialog...
Object oUnoDialog = xMultiComponentFactory.createInstanceWithContext("com.sun.star.awt.UnoControlDialog", xComponentContext);
xDialogControl = (XControl) UnoRuntime.queryInterface(XControl.class, oUnoDialog);
// The scope of the control container is public...
xDialogContainer = (XControlContainer) UnoRuntime.queryInterface(XControlContainer.class, oUnoDialog);
// link the dialog and its model...
XControlModel xControlModel = (XControlModel) UnoRuntime.queryInterface(XControlModel.class, oDialogModel);
xDialogControl.setModel(xControlModel);
// Create a unique name
String uniqueName = createUniqueName(xDialogModelNameContainer, (name != null)? name: "OOoDialog");
// Define the dialog at the model
XPropertySet xDialogPropertySet = (XPropertySet) UnoRuntime.queryInterface(XPropertySet.class, xDialogModelNameContainer);
xDialogPropertySet.setPropertyValue("PositionX",new Integer(posX));
xDialogPropertySet.setPropertyValue("PositionY",new Integer(posY));
xDialogPropertySet.setPropertyValue("Height",new Integer(height));
xDialogPropertySet.setPropertyValue("Width",new Integer(width));
xDialogPropertySet.setPropertyValue("Title",(title != null)? title: "OpenOffice.org Dialog");
xDialogPropertySet.setPropertyValue("Name",uniqueName);
xDialogPropertySet.setPropertyValue("Moveable",Boolean.TRUE);
xDialogPropertySet.setPropertyValue("TabIndex",new Short((short) 0));
}
public short execute() throws Exception {
XWindow xWindow = (XWindow) UnoRuntime.queryInterface(XWindow.class, xDialogContainer);
// set the dialog invisible until it is executed
xWindow.setVisible(false);
Object oToolkit = xMultiComponentFactory.createInstanceWithContext("com.sun.star.awt.Toolkit", xComponentContext);
XWindowPeer xWindowParentPeer = ((XToolkit) UnoRuntime.queryInterface(XToolkit.class, oToolkit)).getDesktopWindow();
XToolkit xToolkit = (XToolkit) UnoRuntime.queryInterface(XToolkit.class, oToolkit);
xDialogControl.createPeer(xToolkit, xWindowParentPeer);
// the return value contains information about how the dialog has been closed
XDialog xDialog = (XDialog) UnoRuntime.queryInterface(XDialog.class, xDialogControl);
return xDialog.execute();
}
public void dispose() {
// Free the resources
XComponent xDialogComponent = (XComponent) UnoRuntime.queryInterface(XComponent.class, xDialogControl);
xDialogComponent.dispose();
}
public XFixedText insertFixedText(int posX, int posY, int width, String label) throws Exception {
// Create a unique name
String uniqueName = createUniqueName(xDialogModelNameContainer, "FixedText");
// Create a fixed text control model
Object oFixedTextModel = xMultiComponentFactoryDialogModel.createInstance("com.sun.star.awt.UnoControlFixedTextModel");
// Set the properties at the model
XPropertySet xFixedTextPropertySet = (XPropertySet) UnoRuntime.queryInterface(XPropertySet.class, oFixedTextModel);
xFixedTextPropertySet.setPropertyValue("PositionX",new Integer(posX));
xFixedTextPropertySet.setPropertyValue("PositionY",new Integer(posY+2));
xFixedTextPropertySet.setPropertyValue("Height",new Integer(8));
xFixedTextPropertySet.setPropertyValue("Width",new Integer(width));
xFixedTextPropertySet.setPropertyValue("Label",(label != null)? label: "");
xFixedTextPropertySet.setPropertyValue("Name",uniqueName);
// Add the model to the dialog model name container
xDialogModelNameContainer.insertByName(uniqueName, oFixedTextModel);
// Reference the control by the unique name
XControl xFixedTextControl = xDialogContainer.getControl(uniqueName);
return (XFixedText) UnoRuntime.queryInterface(XFixedText.class, xFixedTextControl);
}
public XButton insertButton(int posX, int posY, int width, String label, int pushButtonType) throws Exception {
// Create a unique name
String uniqueName = createUniqueName(xDialogModelNameContainer, "Button");
// Create a button control model
Object oButtonModel = xMultiComponentFactoryDialogModel.createInstance("com.sun.star.awt.UnoControlButtonModel");
// Set the properties at the model
XPropertySet xButtonPropertySet = (XPropertySet) UnoRuntime.queryInterface(XPropertySet.class, oButtonModel);
xButtonPropertySet.setPropertyValue("PositionX",new Integer(posX));
xButtonPropertySet.setPropertyValue("PositionY",new Integer(posY));
xButtonPropertySet.setPropertyValue("Height",new Integer(14));
xButtonPropertySet.setPropertyValue("Width",new Integer(width));
xButtonPropertySet.setPropertyValue("Label",(label != null)? label: "");
xButtonPropertySet.setPropertyValue("PushButtonType",new Short((short) pushButtonType));
xButtonPropertySet.setPropertyValue("Name",uniqueName);
// Add the model to the dialog model name container
xDialogModelNameContainer.insertByName(uniqueName, oButtonModel);
// Reference the control by the unique name
XControl xButtonControl = xDialogContainer.getControl(uniqueName);
return (XButton) UnoRuntime.queryInterface(XButton.class, xButtonControl);
}
public XTextComponent insertTextField(int posX, int posY, int width, String text) throws Exception {
return insertEditableTextField(posX, posY, width, text, ' ');
}
public XTextComponent insertPasswordField(int posX, int posY, int width, String text, char echoChar) throws Exception {
return insertEditableTextField(posX, posY, width, text, echoChar);
}
private XTextComponent insertEditableTextField(int posX, int posY, int width, String text, char echoChar) throws Exception {
// Create a unique name
String uniqueName = createUniqueName(xDialogModelNameContainer, "EditableTextField");
// Create an editable text field control model
Object oEditableTextFieldModel = xMultiComponentFactoryDialogModel.createInstance("com.sun.star.awt.UnoControlEditModel");
// Set the properties at the model
XPropertySet xEditableTextFieldPropertySet = (XPropertySet) UnoRuntime.queryInterface(XPropertySet.class, oEditableTextFieldModel);
xEditableTextFieldPropertySet.setPropertyValue("PositionX",new Integer(posX));
xEditableTextFieldPropertySet.setPropertyValue("PositionY",new Integer(posY));
xEditableTextFieldPropertySet.setPropertyValue("Height",new Integer(12));
xEditableTextFieldPropertySet.setPropertyValue("Width",new Integer(width));
xEditableTextFieldPropertySet.setPropertyValue("Text",(text != null)? text: "");
xEditableTextFieldPropertySet.setPropertyValue("Name",uniqueName);
if (echoChar != 0 && echoChar != ' ') {
// Useful for password fields
xEditableTextFieldPropertySet.setPropertyValue("EchoChar",new Short((short) echoChar));
}
// Add the model to the dialog model name container
xDialogModelNameContainer.insertByName(uniqueName, oEditableTextFieldModel);
// Reference the control by the unique name
XControl xEditableTextFieldControl = xDialogContainer.getControl(uniqueName);
return (XTextComponent) UnoRuntime.queryInterface(XTextComponent.class, xEditableTextFieldControl);
}
/**
* Makes a string unique by appending a numerical suffix.
*
* @param elementContainer The container the new element is going to be inserted to
* @param elementName The name of the element
*/
private static String createUniqueName(XNameAccess elementContainer, String elementName) {
String uniqueElementName = elementName;
boolean elementExists = true;
int i = 1;
while (elementExists) {
elementExists = elementContainer.hasByName(uniqueElementName);
if (elementExists) {
i++;
uniqueElementName = elementName + Integer.toString(i);
}
}
return uniqueElementName;
}
}
SmtpMailSender.java
Code: Select all
package util.mail;
import java.util.Properties;
import java.util.StringTokenizer;
import javax.activation.DataHandler;
import javax.mail.Address;
import javax.mail.Authenticator;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
/**
* Mail sender for sending mails via smtp with password authentication.
*/
public class SmtpMailSender implements MailSender {
/** Mail sender configuration */
private MailSenderConfiguration config;
/**
* Constructs a mail sender which uses the mail sender configuration.
*
* @param mailSenderConfiguration The mail sender configuration
*/
public SmtpMailSender(MailSenderConfiguration mailSenderConfiguration) {
config = mailSenderConfiguration;
try {
DataHandler.setDataContentHandlerFactory(new MailContentFactory());
}
catch (java.lang.Error error) {
System.out.println("DataContentHandlerFactory already defined: "+error.getMessage());
}
}
/**
* Sends a text mail with the given content.
*
* @param content The mail content
*/
public void send(Object content) throws MessagingException {
Properties mailProperties = new Properties();
mailProperties.put("mail.smtp.host", config.getSmtpHost());
mailProperties.put("mail.smtp.auth", "true");
Authenticator smtpAuthenticator = new SmtpMailAuthenticator(config.getUser(),config.getPassword());
Session smtpSession = Session.getInstance(mailProperties,smtpAuthenticator);
if (smtpSession != null) {
StringTokenizer tokenizer = new StringTokenizer(config.getRecipients(),";");
Address[] addresses = new InternetAddress[tokenizer.countTokens()];
int i = 0;
while (tokenizer.hasMoreTokens()) {
String recipient = tokenizer.nextToken();
addresses[i] = new InternetAddress(recipient);
i++;
}
Message mimeMessage = new MimeMessage(smtpSession);
mimeMessage.setFrom(new InternetAddress(config.getSender()));
mimeMessage.setRecipients(Message.RecipientType.TO,addresses);
mimeMessage.setSubject(config.getSubject());
mimeMessage.setContent(content, "text/plain");
mimeMessage.saveChanges();
Transport transport = smtpSession.getTransport("smtp");
transport.connect();
transport.sendMessage(mimeMessage,addresses);
transport.close();
}
}
/**
* Authenticator for sending mails via smtp with password authentication.
*
* @param content The mail content
*/
private class SmtpMailAuthenticator extends Authenticator {
private String user;
private String password;
public SmtpMailAuthenticator(String user, String password) {
super();
this.user = user;
this.password = password;
}
@Override
public PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(user,password);
}
}
}
MailSender.java
Code: Select all
package util.mail;
import javax.mail.MessagingException;
public interface MailSender {
/**
* Sends a text mail with the given content.
*
* @param content The mail content
*/
void send(Object content) throws MessagingException;
}
MailSenderConfiguration.java
Code: Select all
package util.mail;
/**
* Configuration for sending a mail.
*/
public class MailSenderConfiguration {
private String sender;
private String smtpHost;
private String user;
private String password;
private String subject;
private String recipients;
public MailSenderConfiguration() {
this.sender = null;
this.smtpHost = null;
this.user = null;
this.password = null;
this.subject = null;
this.recipients = null;
}
public MailSenderConfiguration(String sender, String smtpHost, String user, String password, String subject, String recipients) {
this.sender = sender;
this.smtpHost = smtpHost;
this.user = user;
this.password = password;
this.subject = subject;
this.recipients = recipients;
}
public String getSender() {
return sender;
}
public void setSender(String sender) {
this.sender = sender;
}
public String getSmtpHost() {
return smtpHost;
}
public void setSmtpHost(String smtpHost) {
this.smtpHost = smtpHost;
}
public String getUser() {
return user;
}
public void setUser(String user) {
this.user = user;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getSubject() {
return subject;
}
public void setSubject(String subject) {
this.subject = subject;
}
public String getRecipients() {
return recipients;
}
public void setRecipients(String recipients) {
this.recipients = recipients;
}
}
MailContentFactory.java
Code: Select all
package util.mail;
import javax.activation.DataContentHandler;
import javax.activation.DataContentHandlerFactory;
/**
* Creates a data content handler to handle plain text mails.
*
* http://forum.java.sun.com/thread.jspa?threadID=152756&messageID=441269
*/
public class MailContentFactory implements DataContentHandlerFactory {
public DataContentHandler createDataContentHandler(String contentType) {
if (contentType == null)
return null;
if(contentType.equalsIgnoreCase("text/plain")) {
return new com.sun.mail.handlers.text_plain();
}
return null;
}
}
Configuration files
The script needs three configuration files:
- parcel-descriptor.xml contains the script configuration so that OOo can find an execute the script
- log4j.properties contains the logging configuration
- mail.properties contains the settings for sending the mail via smtp with password authentication
Code: Select all
<?xml version="1.0" encoding="UTF-8"?>
<parcel language="Java" xmlns:parcel="scripting.dtd">
<script language="Java">
<locale lang="en">
<description>Sends a text email from an OOo Writer document.</description>
</locale>
<logicalname value="TextEmailSender"/>
<functionname value="ooo.scripting.writer.TextEmailSender.sendTextEmail"/>
<languagedepprops>
<prop name="classpath" value=".:config:OOoTextMailSender.jar:apache/log4j-1.2.16.jar:mail/mail.jar"/>
</languagedepprops>
</script>
</parcel>
log4j.properties (change the names of the folders of the logging files if necessary)
Code: Select all
log4j.rootLogger = DEBUG, Console, DebugFile, ErrorFile
log4j.appender.Console = org.apache.log4j.ConsoleAppender
log4j.appender.Console.layout = org.apache.log4j.PatternLayout
log4j.appender.Console.layout.ConversionPattern = %d{ISO8601} %-5p [%t] %c: %m%n
log4j.appender.DebugFile = org.apache.log4j.FileAppender
log4j.appender.DebugFile.append = true
log4j.appender.DebugFile.file = c:/temp/debug.log
log4j.appender.DebugFile.layout = org.apache.log4j.PatternLayout
log4j.appender.DebugFile.layout.ConversionPattern = %d{ISO8601} %-5p [%t] %c: %m%n
log4j.appender.DebugFile.level = DEBUG
log4j.appender.ErrorFile = org.apache.log4j.FileAppender
log4j.appender.ErrorFile.append = true
log4j.appender.ErrorFile.file = c:/temp/error.log
log4j.appender.ErrorFile.layout = org.apache.log4j.PatternLayout
log4j.appender.ErrorFile.layout.ConversionPattern = %d{ISO8601} %-5p [%t] %c: %m%n
log4j.appender.ErrorFile.threshold = ERROR
mail.properties (add your mail account settings and recipients proposal here)
Code: Select all
#
# mail properties
#
# email address of sender account
mail.smtpauth.sender =
# host name of sender account
mail.smtpauth.host =
# user name of sender account
mail.smtpauth.user =
# password of sender account
mail.smtpauth.password =
# mail recipients
mail.recipients.proposal =
Deploy the script
The following steps are necessary to get the script running:
- Follow the steps described in the post [Java] OOo Writer and Calc macro examples (steps 1) through 6) below the second Java source code, add additionally the above mentioned JAR files in step 4) and use in step 5) the source code files of this script with their appropriate package names ooo.dialog, ooo.scripting.writer and util.mail) to compile the source code and to create a JAR file containing the script. According to the "parcel-descriptor.xml" as shown above this JAR file should be named OOoTextMailSender.jar. Otherwise the "parcel-descriptor.xml" must be change adequately.
- Create a new folder in the OOo user directory script folder. On a Windows system the name of this folder is something like "c:\documents and settings\<USERNAME>\application data\OpenOffice.org2\user\Scripts\". Create inside this folder a subfolder "java" and within that another like "sendmail" for example. The complete name of the folder for this script is than something like "c:\documents and settings\<USERNAME>\application data\OpenOffice.org2\user\Scripts\java\sendmail". Create additionally inside this folder three subfolders: "apache", "config", "mail".
- Following the "parcel-descriptor.xml" file from above put the following files in the newly-created subfolders:
- parcel-descriptor.xml and the JAR file containing the script (OOoTextMailSender.jar, see above) from step 1. into "sendmail"
- log4j-1.2.16.jar into "sendmail\apache"
- log4j.properties and mail.properties into "sendmail\config"
- mail.jar into "sendmail\mail"
Use the script
The following steps are necessary to execute the script:
- Start OOo (if it is already running, exit OOo and restart it).
- Open an OOo Writer document and call the TextEmailSender script through
- "Tools" > "Macros" > "Run Macro..."
- Expand the tree Library of My Macros and select the library sendmail
- Select the Java macro ooo.scripting.writer.TextEmailSender.sendTextEmail and press the button "Run"
Classpath of the parcel-descriptor.xml
In this script I've used several JAR files, which must be put into the classpath of the parcel-descriptor.xml file. The ability of the parcel-descriptor's classpath is limited compared to a Java classpath in general. In a parcel-descriptor you cannot add an absolute folder or JAR file name to the classpath. All folders and JAR files must reside inside the folder, the parcel-descriptor.xml file is located in, or in subfolders of this folder. This classpath limitation is caused by the way the ScriptProviderForJava builds the classpath. The ScriptProviderForJava uses in its ScriptImpl the class ScriptMetaData. The ScriptMetaData provides a method getClassPath() which uses PathUtils.make_url(). In PathUtils.make_url() the StringBuffer which is used to build the URL is always initialized with the base url (the folder the parcel-descriptor.xml file is located in) of the script. This makes the usage of an absolute folder name impossible.
In the parcel-descriptor above I added the current folder ., the subfolder config and all the above mentioned JAR files with the folder they are located in. The current folder . is not necessary. Very important is the subfolder config in the classpath, so that log4j can find it's properties file and the mail properties can be located. Equally important is to put all the JAR files in the classpath.
A parcel-descriptor.xml can contain several <script> tags. Each <script> has its own <languagedepprops> tag. So every Java script can and must use its own classpath. If no classpath is provided at all, the current folder . (the folder the parcel-descriptor.xml file is located in) is provided for the script.