Index: build/resources/META-INF/smack.providers
===================================================================
--- build/resources/META-INF/smack.providers	(revision 4389)
+++ build/resources/META-INF/smack.providers	(revision 4390)
@@ -180,4 +180,16 @@
         <className>org.jivesoftware.smackx.provider.IBBProviders$Data</className>
     </extensionProvider>
 
+    <iqProvider>
+    	<elementName>new-mail</elementName>
+    	<namespace>google:mail:notify</namespace>
+    	<className>org.jivesoftware.smackx.provider.GoogleMailProviders$NewMail</className>
+    </iqProvider>
+
+    <iqProvider>
+    	<elementName>mailbox</elementName>
+    	<namespace>google:mail:notify</namespace>
+    	<className>org.jivesoftware.smackx.provider.GoogleMailProviders$Mailbox</className>
+    </iqProvider>
+
 </smackProviders>
\ No newline at end of file
Index: source/org/jivesoftware/smackx/provider/GoogleMailProviders.java
===================================================================
--- source/org/jivesoftware/smackx/provider/GoogleMailProviders.java	(revision 4389)
+++ source/org/jivesoftware/smackx/provider/GoogleMailProviders.java	(revision 4390)
@@ -0,0 +1,120 @@
+/**
+ * $RCSfile$
+ * $Revision: 3963 $
+ * $Date: 2006-04-04 14:15:59 +0000 (mar, 04 abr 2006) $
+ *
+ * Copyright 2006 BuddyStream, LLC.
+ *
+ * All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jivesoftware.smackx.provider;
+
+import org.jivesoftware.smack.packet.IQ;
+import org.jivesoftware.smack.packet.PacketExtension;
+import org.jivesoftware.smack.provider.IQProvider;
+import org.jivesoftware.smack.util.PacketParserUtils;
+import org.jivesoftware.smackx.packet.GoogleMailExtensions;
+import org.xmlpull.v1.XmlPullParser;
+
+/**
+ * Parses a Google Mail notify packet.
+ * 
+ * @author Javier Kohen
+ */
+public class GoogleMailProviders {
+	/**
+	 * Parses a new mail notification packet.
+	 * 
+	 * @author Javier Kohen
+	 */
+	public static class NewMail implements IQProvider {
+		public IQ parseIQ(XmlPullParser parser) throws Exception {
+			return new GoogleMailExtensions.NewMail();
+		}
+	}
+
+	/**
+	 * Parses a mailbox packet.
+	 * 
+	 * @author Javier Kohen
+	 */
+	public static class Mailbox implements IQProvider {
+		public IQ parseIQ(XmlPullParser parser) throws Exception {
+			String url = parser.getAttributeValue("", "url");
+			int totalMatched = Integer.parseInt(parser.getAttributeValue("", "total-matched"));
+			long timestamp = Long.parseLong(parser.getAttributeValue("", "result-time"));
+
+			GoogleMailExtensions.Mailbox mailbox = new GoogleMailExtensions.Mailbox(url, totalMatched, timestamp);
+			GoogleMailExtensions.MailThreadInfo mail = null;
+        	GoogleMailExtensions.Sender sender = null;
+        	StringBuilder buf = new StringBuilder();
+	        boolean done = false;
+	        while (!done) {
+	            int eventType = parser.next();
+				if (eventType == XmlPullParser.START_TAG) {
+		            String elementName = parser.getName();
+                	if ("mail-thread-info".equals(elementName)) {
+	                    String threadId = parser.getAttributeValue("", "tid");
+	                    String mailUrl = parser.getAttributeValue("", "url");
+	                    int participation = Integer.parseInt(parser.getAttributeValue("", "participation"));
+	                    int numMessages = Integer.parseInt(parser.getAttributeValue("", "messages"));
+	                    long date = Long.parseLong(parser.getAttributeValue("", "date"));
+	                	mail = new GoogleMailExtensions.MailThreadInfo(threadId, mailUrl, participation, numMessages, date);
+	                } else if ("senders".equals(elementName)) {
+	                	// Swallow event to avoid sender elements being processed as en extension.
+	                } else if ("sender".equals(elementName)) {
+	                	String address = parser.getAttributeValue("", "address");
+	                	String name = parser.getAttributeValue("", "name");
+	                	boolean originator = "1".equals(parser.getAttributeValue("", "originator"));
+	                	boolean unread = "1".equals(parser.getAttributeValue("", "unread"));
+	                	sender = new GoogleMailExtensions.Sender(address, name, originator, unread);
+	                } else if ("labels".equals(elementName)
+	                		|| "subject".equals(elementName)
+	                		|| "snippet".equals(elementName)) {
+	                	buf.setLength(0);
+	                } else {
+	                	// Otherwise, it must be a packet extension.
+	                    PacketExtension extension =
+	                    	PacketParserUtils.parsePacketExtension(
+	                    			parser.getName(), parser.getNamespace(), parser);
+	                	mailbox.addExtension(extension);
+	                }
+	            } else if (eventType == XmlPullParser.TEXT) {
+	            	buf.append(parser.getText());
+	            } else if (eventType == XmlPullParser.END_TAG) {
+		            String elementName = parser.getName();
+	                if ("mail-thread-info".equals(elementName)) {
+	                	mailbox.addMailThreadInfo(mail);
+	                	mail = null;
+	                } else if ("sender".equals(elementName)) {
+	                	if (null != mail)
+	                		mail.addSender(sender);
+	                } else if ("labels".equals(elementName)) {
+	                	if (null != mail)
+	                		mail.setLabels(buf.toString());
+	                } else if ("subject".equals(elementName)) {
+	                	if (null != mail)
+	                		mail.setSubject(buf.toString());
+	                } else if ("snippet".equals(elementName)) {
+	                	if (null != mail)
+	                		mail.setSnippet(buf.toString());
+	                } else if ("mailbox".equals(elementName)) {
+	                    done = true;
+	                }
+	            }
+	        }
+
+	        return mailbox;
+		}
+	}
+}
Index: source/org/jivesoftware/smackx/packet/GoogleMailExtensions.java
===================================================================
--- source/org/jivesoftware/smackx/packet/GoogleMailExtensions.java	(revision 4389)
+++ source/org/jivesoftware/smackx/packet/GoogleMailExtensions.java	(revision 4390)
@@ -0,0 +1,318 @@
+/**
+ * $RCSfile$
+ * $Revision: 3963 $
+ * $Date: 2006-04-04 14:15:59 +0000 (mar, 04 abr 2006) $
+ *
+ * Copyright 2006 BuddyStream, LLC.
+ *
+ * All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jivesoftware.smackx.packet;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.jivesoftware.smack.packet.IQ;
+
+/**
+ * Different extensions used for mail fetching and notification.
+ * 
+ * @author Javier Kohen
+ */
+public class GoogleMailExtensions {
+	public static final String NAMESPACE = "google:mail:notify";
+
+	/**
+	 * Represents a packet to query the server for the mailbox status.
+	 * 
+	 * @author Javier Kohen
+	 */
+	public static class Query extends IQ {
+		public static final String ELEMENT_NAME = "query";
+
+		/**
+		 * Constructs a query packet.
+		 */
+		public Query() {
+		}
+
+		public String getElementName() {
+			return ELEMENT_NAME;
+		}
+
+		public String getChildElementXML() {
+			StringBuilder buf = new StringBuilder();
+			buf.append("<").append(getElementName());
+			buf.append(" xmlns=\"").append(getNamespace()).append("\" />");
+			return buf.toString();
+		}
+
+		public String getNamespace() {
+			return NAMESPACE;
+		}
+	}
+
+	/**
+	 * Represents a notification that new mail has arrived.
+	 * 
+	 * @author Javier Kohen
+	 */
+	public static class NewMail extends IQ {
+		public static final String ELEMENT_NAME = "new-mail";
+
+		/**
+		 * Constructs a new mail packet.
+		 */
+		public NewMail() {
+		}
+
+		public String getElementName() {
+			return ELEMENT_NAME;
+		}
+
+		public String getChildElementXML() {
+			StringBuilder buf = new StringBuilder();
+			buf.append("<").append(getElementName());
+			buf.append(" xmlns=\"").append(getNamespace()).append("\" />");
+			return buf.toString();
+		}
+
+		public String getNamespace() {
+			return NAMESPACE;
+		}
+	}
+
+	/**
+	 * A mailbox packet containing a description of the mailbox' contents.
+	 * 
+	 * @author Javier Kohen
+	 */
+	public static class Mailbox extends IQ {
+		public static final String ELEMENT_NAME = "mailbox";
+
+		private final List<MailThreadInfo> mailThreadInfos = new ArrayList<MailThreadInfo>();
+
+		private final String url;
+		private final int totalMatched;
+		private final long timestamp;
+
+		public Mailbox(String url, int totalMatched, long timestamp) {
+			this.url = url;
+			this.timestamp = timestamp;
+			this.totalMatched = totalMatched;
+		}
+
+		public String getElementName() {
+			return ELEMENT_NAME;
+		}
+
+		/**
+		 * Returns the number of mails that matched the associated mailbox query.
+		 * 
+		 * @return the number of mails that matched the query.
+		 */
+		public int getTotalMatched() {
+			return totalMatched;
+		}
+
+		/**
+		 * Returns the timestamp associated with this packet. This field is
+		 * called <em>result-time</em> in the protocol.
+		 * 
+		 * @return the timestamp associated with this packet.
+		 */
+		public long getTimestamp() {
+			return timestamp;
+		}
+
+		/**
+		 * Returns the HTTP URL pointing to the mailbox.
+		 * 
+		 * @return Returns an HTTP URL that points to the mailbox.
+		 */
+		public String getUrl() {
+			return url;
+		}
+
+		public String getNamespace() {
+			return NAMESPACE;
+		}
+
+		public void addMailThreadInfo(MailThreadInfo mailThreadInfo) {
+			mailThreadInfos.add(mailThreadInfo);
+		}
+
+		public MailThreadInfo[] getMailThreadInfos() {
+			return mailThreadInfos.toArray(new MailThreadInfo[mailThreadInfos.size()]);
+		}
+
+		public String getChildElementXML() {
+			StringBuilder buf = new StringBuilder();
+			buf.append("<").append(getElementName());
+			buf.append(" xmlns=\"").append(getNamespace()).append("\" ");
+			buf.append("url=\"").append(getUrl()).append("\" ");
+			buf.append("total-matched=\"").append(getTotalMatched()).append("\"");
+			buf.append("result-time=\"").append(getTimestamp()).append("\"");
+			buf.append(">");
+			for (MailThreadInfo mailThreadInfo : mailThreadInfos)
+				mailThreadInfo.toXML(buf);
+			buf.append("</").append(getElementName()).append(">");
+			return buf.toString();
+		}
+	}
+
+	/**
+	 * Contains information describing a mail thread, such as number of messages,
+	 * URL, senders, subject and a snippet of the mail.
+	 * 
+	 * @author Javier Kohen
+	 */
+	public static class MailThreadInfo {
+		private final List<Sender> senders = new ArrayList<Sender>();
+
+		private final String threadId;
+		private final String url;
+		private final int participation;
+		private final int numMessages;
+		private final long date;
+
+		private String labels;
+		private String subject;
+		private String snippet;
+
+		public MailThreadInfo(String threadId, String url, int participation,
+				int numMessages, long date) {
+			this.threadId = threadId;
+			this.url = url;
+			this.participation = participation;
+			this.numMessages = numMessages;
+			this.date = date;
+		}
+
+		public final long getDate() {
+			return date;
+		}
+
+		public final String getLabels() {
+			return labels;
+		}
+
+		public final void setLabels(String labels) {
+			this.labels = labels;
+		}
+
+		public final int getNumMessages() {
+			return numMessages;
+		}
+
+		public final int getParticipation() {
+			return participation;
+		}
+
+		public final Sender[] getSenders() {
+			return senders.toArray(new Sender[senders.size()]);
+		}
+
+		public final void addSender(Sender sender) {
+			senders.add(sender);
+		}
+
+		public final String getSnippet() {
+			return snippet;
+		}
+
+		public final void setSnippet(String snippet) {
+			this.snippet = snippet;
+		}
+
+		public final String getSubject() {
+			return subject;
+		}
+
+		public final void setSubject(String subject) {
+			this.subject = subject;
+		}
+
+		public final String getThreadId() {
+			return threadId;
+		}
+
+		public final String getUrl() {
+			return url;
+		}
+
+		public void toXML(StringBuilder buf) {
+			buf.append("<mail-thread-info ");
+			buf.append("tid=\"").append(getThreadId()).append("\" ");
+			buf.append("url=\"").append(getUrl()).append("\" ");
+			buf.append("participation=\"").append(getParticipation()).append("\"");
+			buf.append("messages=\"").append(getNumMessages()).append("\"");
+			buf.append("date=\"").append(getDate()).append("\"");
+			buf.append(">");
+			buf.append("<senders>");
+			for (Sender sender : senders)
+				sender.toXML(buf);
+			buf.append("</senders>");
+			buf.append("<labels>").append(getLabels()).append("</labels>");
+			buf.append("<subject>").append(getSubject()).append("</subject>");
+			buf.append("<snippet>").append(getSnippet()).append("</snippet>");
+			buf.append("</mail-thread-info>");
+		}
+	}
+
+	/**
+	 * Describes the sender of an e-mail.
+	 * 
+	 * @author Javier Kohen
+	 */
+	public static class Sender {
+		private final String address;
+		private final String name;
+		private final boolean originator;
+		private final boolean unread;
+
+		public Sender(String address, String name, boolean originator, boolean unread) {
+			this.address = address;
+			this.name = name;
+			this.originator = originator;
+			this.unread = unread;
+		}
+
+		public final String getAddress() {
+			return address;
+		}
+
+		public final String getName() {
+			return name;
+		}
+
+		public final boolean isOriginator() {
+			return originator;
+		}
+
+		public final boolean isUnread() {
+			return unread;
+		}
+
+		public void toXML(StringBuilder buf) {
+			buf.append("<sender ");
+			buf.append("address=\"").append(getAddress()).append("\" ");
+			if (null != getName()) {
+				buf.append("name=\"").append(getName()).append("\" ");
+			}
+			buf.append("originator=\"").append(isOriginator() ? 1 : 0).append("\"");
+			buf.append("unread=\"").append(isUnread() ? 1 : 0).append("\"");
+			buf.append("/>");
+		}
+	}
+}
Index: source/org/jivesoftware/smackx/packet/GoogleSetting.java
===================================================================
--- source/org/jivesoftware/smackx/packet/GoogleSetting.java	(revision 4389)
+++ source/org/jivesoftware/smackx/packet/GoogleSetting.java	(revision 4390)
@@ -0,0 +1,89 @@
+/**
+ * $RCSfile$
+ * $Revision: 3963 $
+ * $Date: 2006-04-04 14:15:59 +0000 (mar, 04 abr 2006) $
+ *
+ * Copyright 2006 BuddyStream, LLC.
+ *
+ * All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jivesoftware.smackx.packet;
+
+import org.jivesoftware.smack.packet.IQ;
+
+/**
+ * A GoogleSetting IQ packet, which is used by XMPP clients to request and
+ * receive user setting information to/from the Google Talk server.
+ * 
+ * <p>When changing the settings on the server, the packet should be addressed
+ * to the bare address of the local user.
+ * </p>
+ * 
+ * @author Javier Kohen
+ */
+public class GoogleSetting extends IQ {
+	/** Whether the client wants to receive mail notifications from the server. */
+	private Boolean mailNotifications;
+
+	/**
+	 * Returns whether mail notifications have been set and enabled. If
+	 * <code>isMailNotificationsSet</code> returns <code>false</code>,
+	 * then this method also returns false.
+	 * 
+	 * @return whether mail notifications are enabled or not.
+	 */
+	public boolean isMailNotificationsEnabled() {
+		return null != mailNotifications && mailNotifications;
+	}
+
+	/**
+	 * Sets whether mail notifications will be enabled or disabled. If you
+	 * changed your mind and do not wish to change this setting on the server,
+	 * then invoke method <code>forgetMailNotifications</code>.
+	 * 
+	 * @param enabled whether mail notifications shall be enabled.
+	 */
+	public void setMailNotificationsEnabled(boolean enabled) {
+		mailNotifications = enabled;
+	}
+
+	/**
+	 * Returns whether the mail notification setting has been given a value.
+	 * When <code>false</code>, the setting will not be changed in the server.
+	 * 
+	 * @return whether the mail notification settin has been set.
+	 */
+	public boolean isMailNotificationsSet() {
+		return null != mailNotifications;
+	}
+
+	/**
+	 * Causes the previously setting of the mail notification field to be lost.
+	 * This prevents the setting from being modified on the server.
+	 */
+	public void forgetMailNotifications() {
+		mailNotifications = null;
+	}
+
+	public String getChildElementXML() {
+		StringBuilder buf = new StringBuilder();
+		buf.append("<usersetting xmlns=\"google:setting\">");
+		if (isMailNotificationsSet()) {
+			buf.append("<mailnotifications value=\"");
+			buf.append(isMailNotificationsEnabled());
+			buf.append("\" />");
+		}
+		buf.append("</usersetting>");
+		return buf.toString();
+	}
+}
