It's all about the answers!

Ask a question

Resolved: [Not a] Bug with user mail settings and receiveMails?


0
2
Sterling Bates (2311612) | asked Dec 23 '13, 10:56 a.m.
edited Dec 24 '13, 4:21 a.m.
I used the Java API to modify the receiveMails setting for my own user as a test, and now I no longer receive email updates from any work items.  I've verified that the box is checked in the Eclipse client--I also tried unsetting and re-setting it--but still no emails.

Is there possibly a backend issue with this field?  I'm going to be making a bunch of updates soon, and to avoid flooding mailboxes I'm modifying many users in the same manner, and don't want to entirely lose email updates to all developers.

Some sample code (though I do a little abstracting of the RTC API, so I can't post the whole thing):

private static final String MAIL_SETTINGS = "com.ibm.team.workitem.mail.Configuration";
IContributorDetails details = (IContributorDetails)getContributorDetails(contributorWC).getWorkingCopy();
String settings = details.getLargeStringExtension(MAIL_SETTINGS);
settings = settings.replace("<receiveMails value=\"false\"/>", "<receiveMails value=\"true\"/>");
details.setLargeStringExtension(MAIL_SETTINGS, settings);
mgr.getContributorManager().setContributorDetails(getContributorHandle(), details, null);



Comments
Matthew Owenby commented May 21 '14, 11:59 a.m.

Sterling,


Would you be willing to share your code?  We are interested in doing this as well. 


VK L commented Feb 03 '15, 4:56 a.m. | edited Feb 24 '18, 5:21 p.m.
Hi All,

I have written a code to update mail format settings - it fails to fetch the contributor details and throuws null exception on the mailconfig retrieval:
*It works after i open the particular user in the editor and perform a save.

user = icm.fetchContributorByUserId(userid, null);
contributorWorkingCopy = (IContributor) user.getWorkingCopy();
icm.saveContributor(contributorWorkingCopy, null);
IContributorDetailsHandle detailsHandle = contributorWorkingCopy.getDetails();
details = (IContributorDetails) iim.fetchCompleteItem(detailsHandle,IItemManager.DEFAULT, null);
details=(IContributorDetails) details.getWorkingCopy();
String mailconfig = details.getLargeStringExtension("com.ibm.team.workitem.mail.Configuration");

mailconfig value is retrieved as null.Please advise.


Mohammed Sardar commented Feb 24 '18, 3:12 p.m. | edited Feb 24 '18, 3:13 p.m.

Thanks. So, in RTC how can we this feature usage ? Is it a contribution to development? Please help. 

Accepted answer


permanent link
Sterling Bates (2311612) | answered Dec 24 '13, 4:19 a.m.
The server on which the repository was running did, in fact, have an email outage.  This API is working fine, but what a coincidence...
Ralph Schoon selected this answer as the correct answer

One other answer



permanent link
sam detweiler (12.4k6171200) | answered Dec 23 '13, 11:15 a.m.
edited Jul 14 '14, 5:40 p.m.
I wrote this to turn off/restore users emails during mass updates
takes a file of userids (1 per line)
or an xml file (you might have one, but have to update the format).
the code figures out what kind of source file it is.
| updated to use product provided constants instead of hard coded literals.
| added support for decypting password
| see the second answer here https://jazz.net/forum/questions/156705/is-there-support-for-password-files-in-the-plain-java-client-api
| for info on encrypting the password

<code>
package com.sd.test;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.StringReader;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Collections;

import javax.xml.parsers.DocumentBuilderFactory;
import org.eclipse.core.runtime.CoreException;
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;

import com.ibm.team.foundation.common.util.IMemento;
import com.ibm.team.foundation.common.util.XMLMemento;
import com.ibm.team.repository.client.IContributorManager;
import com.ibm.team.repository.client.IItemManager;
import com.ibm.team.repository.client.ITeamRepository;
import com.ibm.team.repository.client.TeamPlatform;
import com.ibm.team.repository.client.ITeamRepository.ILoginHandler;
import com.ibm.team.repository.client.ITeamRepository.ILoginHandler.ILoginInfo;
import com.ibm.team.repository.common.IContributor;
import com.ibm.team.repository.common.IContributorDetails;
import com.ibm.team.repository.common.IContributorDetailsHandle;
import com.ibm.team.repository.common.IExtensibleItem;
import com.ibm.team.repository.common.ItemNotFoundException;
import com.ibm.team.repository.common.TeamRepositoryException;
import com.ibm.team.workitem.common.internal.mailconfig.IMailConfigurationConstants;
import com.ibm.team.repository.common.util.ObfuscationHelper;


public class BulkConfigureContributorEmail implements IMailConfigurationConstants
{

    // our hash key to save the content
    private static final String CONFIG_KEY_ORIGINAL = CONFIG_KEY+".original";
    // the default string, cut/pasted
    private static final String DefaultSettings="default";
    private static final String DefaultSettingsString=
            "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n<mailconfiguration version=\"0.6\">\r\n<"+CONFIG_SCOPE_GLOBAL+">\r\n<"+CONFIG_DOMAIN_WORK_ITEMS+">\r\n<"+CONFIG_RECEIVE_MAILS+" value=\"true\"/>\r\n<"+CONFIG_MAIL_WHEN_SUBSCRIBED+" value=\"true\"/>\r\n<filter>\r\n<CREATOR>\r\n<COMMENT_ADDED/>\r\n<SUMMARY_DESCRIPTION_CHANGED/>\r\n<SEVERITY_PRIORITY_TARGET_CHANGED/>\r\n<OWNER_CHANGED/>\r\n<TAG_CHANGED/>\r\n<LINKS_ADDED_REMOVED/>\r\n<WORK_ITEM_CREATED_REOPENED/>\r\n<WORK_ITEM_COMPLETED/>\r\n<OTHER_STATE_CHANGE/>\r\n<OTHER_CHANGE/>\r\n</CREATOR>\r\n<OWNER>\r\n<COMMENT_ADDED/>\r\n<SUMMARY_DESCRIPTION_CHANGED/>\r\n<SEVERITY_PRIORITY_TARGET_CHANGED/>\r\n<OWNER_CHANGED/>\r\n<TAG_CHANGED/>\r\n<LINKS_ADDED_REMOVED/>\r\n<WORK_ITEM_CREATED_REOPENED/>\r\n<WORK_ITEM_COMPLETED/>\r\n<OTHER_STATE_CHANGE/>\r\n<OTHER_CHANGE/>\r\n</OWNER>\r\n<SUBSCRIBER>\r\n<COMMENT_ADDED/>\r\n<SUMMARY_DESCRIPTION_CHANGED/>\r\n<SEVERITY_PRIORITY_TARGET_CHANGED/>\r\n<OWNER_CHANGED/>\r\n<TAG_CHANGED/>\r\n<LINKS_ADDED_REMOVED/>\r\n<WORK_ITEM_CREATED_REOPENED/>\r\n<WORK_ITEM_COMPLETED/>\r\n<OTHER_STATE_CHANGE/>\r\n<OTHER_CHANGE/>\r\n</SUBSCRIBER>\r\n</filter>\r\n</"+CONFIG_DOMAIN_WORK_ITEMS+">\r\n<"+CONFIG_DOMAIN_MESSAGES_AT_ME+">\r\n<"+CONFIG_MAIL_MESSAGES_AT_ME+" value=\"true\"/>\r\n</"+CONFIG_DOMAIN_MESSAGES_AT_ME+">\r\n<approvals>\r\n<"+CONFIG_RECEIVE_MAILS+" value=\"true\"/>\r\n<receiveOwnChanges value=\"false\"/>\r\n</approvals>\r\n<format>\r\n<htmlMail value=\"false\"/>\r\n</format>\r\n</"+CONFIG_SCOPE_GLOBAL+">\r\n</mailconfiguration>";

    // the identifier for the xml content to get to a user entry
    private static final String XMLElementName = "Row";
    private static final String UserIDElementName ="ID";
   
    private static final String operationDisable = "disable";
    private static final String operationRestore = "restore";

    private static class LoginHandler implements ILoginHandler, ILoginInfo
    {

        private String fUserId;
        private String fPassword;

        private LoginHandler(String userId, String password)
        {
            fUserId = userId;
            fPassword = password;
        }

        public String getUserId()
        {
            return fUserId;
        }

        public String getPassword()
        {
            return fPassword;
        }

        public ILoginInfo challenge(ITeamRepository repository)
        {
            return this;
        }
    }
    /**
     * @param args
     */
    public static void main(String[] args)
    {
        // TODO Auto-generated method stub
        String repositoryURI = args[0];
        String AdminUserId = args[1];
        String password = args[2];
        String UserlistFile  = args[3];
        String operation = args[4];

        TeamPlatform.startup();
        ITeamRepository teamRepository = TeamPlatform
                .getTeamRepositoryService().getTeamRepository(repositoryURI);
            try
            {
                // decrypt the user password
                password = ObfuscationHelper.decryptString(password);
            }
            catch(Exception ex)
            {
                // nothin to do, variable not overlayed on error
            }
        teamRepository.registerLoginHandler(new LoginHandler(AdminUserId, password));

        // get the list of users whose email config needs to be changed
        // might be flat file of ids, or xml doc Rows><Row <id>name</id>
        // get the list ready here, if that fails. don't continue
        ArrayList<String> userids = getUseridList(UserlistFile);
        if(userids.size()>0)
        {
            try
            {
                // login
                teamRepository.login(null);
                // if successful
                if(teamRepository.loggedIn())       
                {
                    // get the two workers
                    IContributorManager icm;
                    icm = teamRepository.contributorManager();
                   
                    IItemManager iim;
                    iim = teamRepository.itemManager();
                    // loop thru the userid array
                    for(String userid: userids)
                    {
                        try
                        {
                            // get the user record using the ID string (not the name)
                            IContributor contributor = icm.fetchContributorByUserId(userid, null);
                            // if we found the user in the system
                            if(contributor!=null)
                            {
                                // get the read/write copy of the contributor record
                                contributor = (IContributor) contributor.getWorkingCopy();
                                // set the mail config
                                // either disabled, all
                                // or restored to whatever it was
                                setMailConfiguration(contributor,icm, iim, operation);                   
                            }
                        }
                        catch(ItemNotFoundException ex)
                        {
                            continue;
                        }
                    }
                }
            }
            catch(Exception ex)
            {
                System.out.println("exception="+ex.toString());
            }
        }
        TeamPlatform.shutdown();
       
    }
    public static ArrayList<String> getUseridList(String filename)
    {

        ArrayList<String> userlist = new ArrayList<String>();       
        try
        {
            String line;
           
            BufferedReader br = new BufferedReader(new FileReader(filename));
            // read the first line
            line= br.readLine();
            // if not an xml file
            if(!line.startsWith("<?xml"))
            {
                // save the line to the array
                userlist.add(line);
               
                // read the rest of the user id list
                while((line = br.readLine()) != null)
                     userlist.add(line);
                // close the file
                br.close();

            }
            else
            {
                // close the file
                br.close();       
                // xml file processor
                // document handler will reopen and parse
                Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(new File(filename));;
       
                // normalize text representation
                doc.getDocumentElement().normalize();
               
                // get the list of elements that represent users
                NodeList listOfUsers = doc.getElementsByTagName(XMLElementName);
                //System.out.println("Total no of people : " + listOfUsers.getLength());

                // loop thru the nodes
                for(int i=0;i<listOfUsers.getLength(); i++)
                {
                    NodeList userentry = (NodeList) listOfUsers.item(i);
                    //System.out.println("there are "+ userentry.getLength() + " nodes for this entry");
                    for (int q=0; q<userentry.getLength();q++)
                    {
                        //System.out.println("node "+ q+ " name="+userentry.item(q).getNodeName()+ " value="+userentry.item(q).getFirstChild().getTextContent());
                        // find the specific element that contains the userid data
                        if(userentry.item(q).getNodeName().equalsIgnoreCase(UserIDElementName))
                        {
                            // get the actual user data.. in the Text node
                            // and save it to the array
                            userlist.add(userentry.item(q).getFirstChild().getTextContent());                  
                            break;
                        }
                    }
                }
            }
        }
        catch (Exception ex)
        {
            // TODO Auto-generated catch block
            ex.printStackTrace();
        }
        return userlist;
    }


    private static IMemento setMailConfiguration(IContributor contributor,IContributorManager icm,  IItemManager iim, String operation) throws TeamRepositoryException
    {

        IContributorDetailsHandle detailsHandle= contributor.getDetails();
        if (detailsHandle != null)
        {
            IContributorDetails details=
            (IContributorDetails) iim.fetchPartialItem(detailsHandle, IItemManager.REFRESH, Collections.singleton(IExtensibleItem.ALL_STATE_EXTENSIONS_PROPERTY),null);
            // get the writeable copy of the details
            details=(IContributorDetails) details.getWorkingCopy();   
           
            // if we are restoring the previously set values
            if(operation.equalsIgnoreCase(operationRestore))
            {               
                // get the saved value, if any
                String configVal= details.getLargeStringExtension(CONFIG_KEY_ORIGINAL);
                if(configVal!=null)
                {
                    // if the email value was actually specified
                    if(!configVal.equals(DefaultSettings))
                        // restore it
                        // overlay the current settings with the original saved value
                        details.setLargeStringExtension(CONFIG_KEY, configVal);
                    else
                        // clear the string, system uses the default
                        details.unsetLargeStringExtension(CONFIG_KEY);
                    // and remove the saved value
                    details.unsetLargeStringExtension(CONFIG_KEY_ORIGINAL);
                    // save the details info back;
                    icm.setContributorDetails(contributor, details,null);
                }               
                return null;
            }
            else if(operation.equalsIgnoreCase(operationDisable))
            {
                // get the saved value, if any
                String configVal= details.getLargeStringExtension(CONFIG_KEY_ORIGINAL);
                // do we have a previously saved setup
                // no continue on
                if(configVal==null)
                {
                    // get the RTC data for the mail settings
                    configVal= details.getLargeStringExtension(CONFIG_KEY);
                    // if not set
                    if(configVal==null)
                    {
                        // indicate the defaults were used
                        details.setLargeStringExtension(CONFIG_KEY_ORIGINAL, DefaultSettings);
                        // get the original string copy
                        configVal = DefaultSettingsString;
                    }
                    else
                    {
                        // save the original settings                   
                        details.setLargeStringExtension(CONFIG_KEY_ORIGINAL, configVal);
                    }
                    try
                    {
                        XMLMemento imx = XMLMemento.createReadRoot(new StringReader(configVal));
                        // turn off the global emails
                        imx.getChild(CONFIG_SCOPE_GLOBAL).getChild(CONFIG_DOMAIN_WORK_ITEMS).getChild(CONFIG_RECEIVE_MAILS).putString("value", "false");
                        // and the subscriptions
                        imx.getChild(CONFIG_SCOPE_GLOBAL).getChild(CONFIG_DOMAIN_WORK_ITEMS).getChild(CONFIG_MAIL_WHEN_SUBSCRIBED).putString("value", "false");
                        // and the mentions
                        imx.getChild(CONFIG_SCOPE_GLOBAL).getChild(CONFIG_DOMAIN_MESSAGES_AT_ME).getChild(CONFIG_MAIL_MESSAGES_AT_ME).putString("value", "false");
                        // and the approvals
                        imx.getChild(CONFIG_SCOPE_GLOBAL).getChild(CONFIG_DOMAIN_APPROVALS).getChild(CONFIG_RECEIVE_MAILS).putString("value", "false");
                        StringWriter writer= new StringWriter();
                        // flush into writer
                        imx.save(writer);
                        // save the new settings
                        details.setLargeStringExtension(CONFIG_KEY, writer.toString());
                        // and write back to the contributor
                        icm.setContributorDetails(contributor, details,null);                       
                    }
                    catch (CoreException e)
                    {
                        System.out.println("unable to get contrinutor details");
                        return (IMemento)null;
                    }
                    catch (IOException e)
                    {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }                   
                }
            }
            return (IMemento)null;
        }
        return (IMemento)null;
    }
}


</code>

Comments
Sterling Bates commented Dec 23 '13, 1:47 p.m.

Thanks Sam, though the code I have does work.  It turns out that it might be a repo-wide issue at the server (vacations are heavy at this time so we didn't find out very quickly) and I'll report back when we know for sure.


Christiano Monteiro commented Nov 03 '15, 4:04 p.m. | edited Feb 24 '18, 5:21 p.m.

Hi Sam,

How can we change the filter options (Creator, Owner, Modifier, Subscriber) using the API?


sam detweiler commented Nov 03 '15, 6:12 p.m.

sorry, not sure what you mean..

you mean the values under those headings for each message type?
each checkbox is an XML element, so you have to set its value to true for checked, and false for unchecked.

you will have to search thru the xml document  once you find its structure.
imx.getChild(CONFIG_SCOPE_GLOBAL).getChild(CONFIG_DOMAIN_WORK_ITEMS).getChild(CONFIG_RECEIVE_MAILS).putString("value", "false");

this is not documented for us externals.


Christiano Monteiro commented Nov 04 '15, 8:06 a.m.

Sam,

I found this structure and set the check box values, but the user profile didn't change. I can change only the CONFIG_RECEIVE_MAILS value.

imx.getChild(CONFIG_SCOPE_GLOBAL).getChild(CONFIG_DOMAIN_WORK_ITEMS).getChild(CONFIG_WORK_ITEM_FILTER).getChild(creator).getChild(comment_added).putString("value", "true");


Christiano Monteiro commented Nov 04 '15, 8:52 a.m.

Sam,

Sorry. The xml structure is different. I used this code and it work. Thanks.

imx.getChild(CONFIG_SCOPE_GLOBAL).getChild(CONFIG_DOMAIN_WORK_ITEMS).getChild(CONFIG_WORK_ITEM_FILTER).getChild(CREATOR).getChild(COMMENT_ADDED).putString("value", "true");


sam detweiler commented Nov 04 '15, 8:55 a.m. | edited Nov 04 '15, 9:00 a.m.

I was posting at the same time.. yes.. you found it..

the per change type are in the CONFIG_WORK_ITEM_FILTER structure,
and each column is a xml element structure, <CREATOR></CREATOR><OWNER>>/OWNER> etc..

it looks like if you want the setting ON you include an element, otherwise not.
for example "<CREATOR><COMMENT_ADDED/><SUMMARY_DESCRIPTION_CHANGED/>...</CREATOR>

you can see all this in the default xml structure above


Ralph Schoon commented Oct 11 '16, 9:37 a.m.
FORUM ADMINISTRATOR / FORUM MODERATOR / JAZZ DEVELOPER

Please see Skip Mail Save Parameter since RTC 6.0 iFix03.


sam detweiler commented Oct 11 '16, 10:23 a.m.

while interesting, this doesn't really help in the use cases I see.. bulk import of workitems..  none of my code is involved.


Ralph Schoon commented Oct 11 '16, 10:34 a.m.
FORUM ADMINISTRATOR / FORUM MODERATOR / JAZZ DEVELOPER

I hooked your code answer directly to my blog in one case. Want to make sure they see it if they go here.

showing 5 of 9 show 4 more comments

Your answer


Register or to post your answer.