Finding Links and other stuff in an email with a Gmail Addon regular expressions
This is a regex tester so it's probably more than you were expecting but it will find the links that your looking for as well as any others you wish to find. This one will work for your current needs: <.*q=cats.*>
. The regex function currently being using is String.match you can find it explained here There's a url at the bottom of the page that should point back to a spreadsheet that contains a page named "Default" as explained later.
function buildAddOn(e) {
var accessToken = e.messageMetadata.accessToken;
GmailApp.setCurrentMessageAccessToken(accessToken);
var msg=GmailApp.getMessageById(e.messageMetadata.messageId).getPlainBody();
setDefaults({message:msg});
var cards = [];
cards.push(buildRegexTester(getDefaults()));
return cards;
}
function buildRegexTester(dfltObj){
var card=CardService.newCardBuilder();
card.setHeader(CardService.newCardHeader().setTitle('Regex Tester'));
var section=CardService.newCardSection().setHeader('Email Body Search');
var plainBodyText=CardService.newTextParagraph().setText(dfltObj.message);
section.addWidget(plainBodyText)
var saveRegexButton=CardService.newTextButton().setText('Save Regex').setOnClickAction(CardService.newAction().setFunctionName('saveRegex'));
section.addWidget(saveRegexButton);
var regexTextBox=CardService.newTextInput()
.setFieldName('Regex')
.setTitle('Regex')
.setMultiline(true)
.setValue(dfltObj.Regex);
section.addWidget(regexTextBox);
var searchButton=CardService.newTextButton().setText('Search').setOnClickAction(CardService.newAction().setFunctionName('search'));
section.addWidget(searchButton);
var regexResultBox=CardService.newTextInput()
.setFieldName('Results')
.setTitle('Results')
.setMultiline(true)
.setValue(dfltObj.results);
section.addWidget(regexResultBox);
var clearResultsButton=CardService.newTextButton().setText('Clear Results').setOnClickAction(CardService.newAction().setFunctionName('clearResults'));
section.addWidget(clearResultsButton)
var g_toggle=CardService.newKeyValue()
.setContent('global search')
.setSwitch(CardService.newSwitch()
.setSelected(dfltObj.g)
.setFieldName('g')
.setValue('g')
.setOnChangeAction(CardService.newAction().setFunctionName('saveFlags')));
section.addWidget(g_toggle);
var i_toggle=CardService.newKeyValue()
.setContent('ignore case')
.setSwitch(CardService.newSwitch()
.setSelected(dfltObj.i)
.setFieldName('i')
.setValue('i')
.setOnChangeAction(CardService.newAction().setFunctionName('saveFlags')));
section.addWidget(i_toggle);
var m_toggle=CardService.newKeyValue()
.setContent('multiline search')
.setSwitch(CardService.newSwitch()
.setSelected(dfltObj.m)
.setFieldName('m')
.setValue('m')
.setOnChangeAction(CardService.newAction().setFunctionName('saveFlags')));
section.addWidget(m_toggle);
card.addSection(section);
return card.build();
}
function getDefaults(){
var ss=SpreadsheetApp.openByUrl(RegexTesterAddon_URL);
var sh=ss.getSheetByName('Defaults');
var rg=sh.getDataRange();
var vA=rg.getValues();
var dfltObj={};
for(var i=0;i<vA.length;i++){
dfltObj[vA[i][0]]=vA[i][1];
}
return dfltObj;
}
function setDefaults(dfltObj){
var ss=SpreadsheetApp.openByUrl(RegexTesterAddon_URL);
var sh=ss.getSheetByName('Defaults');
var rg=sh.getDataRange();
var vA=rg.getValues();
for(var i=0;i<vA.length;i++){
if(typeof(dfltObj[vA[i][0]])!='undefined'){
vA[i][1]=dfltObj[vA[i][0]];
}
}
rg.setValues(vA);
}
function saveFlags(e){
Logger.log('\nsaveFlags():\n%s\n',e);
var g=(typeof(e.formInput.g)!='undefined')?true:false;
var i=(typeof(e.formInput.i)!='undefined')?true:false;
var m=(typeof(e.formInput.m)!='undefined')?true:false;
var flagObj={g:g,i:i,m:m};
setDefaults(flagObj);
}
function saveRegex(e){
Logger.log('\nsaveRegex():\n%s',e);
var regex=(typeof(e.formInput.Regex)!='undefined')?e.formInput.Regex:'';
if(regex){
var rObj={Regex:regex};
setDefaults(rObj);
}
}
function saveResults(rsltObj){
setDefaults(rsltObj);
}
function getFlags(){
var dfltObj=getDefaults();
var flagsA=[];
if(dfltObj.g){flagsA.push('g');}
if(dfltObj.i){flagsA.push('i');}
if(dfltObj.m){flagsA.push('m');}
var flags=flagsA.join('');
return flags;
}
function search(e){
Logger.log('\nSearch():\n%s',e);
if(typeof(e.formInput.Regex)!='undefined'){
saveFlags(e);
saveRegex(e);
var dfltObj=getDefaults();
var flags=getFlags();
var pattern=dfltObj.Regex;
Logger.log('\nflags: %s\npattern: %s',flags,pattern);
var re=new RegExp(pattern,flags);
//var result=re.exec(dfltObj.message);
var result=dfltObj.message.match(re);
if(result) {
Logger.log('\nresult: %s\nmessage:',result,dfltObj.message);
if(result){
var rsltLog='';
for(var i=0;i<result.length;i++){
if(i>0){rsltLog+='\n'};
rsltLog+='result[' + i + ']= ' + result[i];
}
}
console.log('module: %s pattern: %s regex: %s flags: %s result: %s length: %s',"findData()",pattern,re,flags,rsltLog,result.length);
}
if(result){
var results=rsltLog;
}else{
var results="No Results";
}
//var rsltObj={results:results};
var rsltObj={results:escapeHtml(results)};
saveResults(rsltObj);
return buildRegexTester(getDefaults());
}
}
function clearResults(e){
var dfltObj=getDefaults();
dfltObj.results='';
return buildRegexTester(dfltObj);
}
//Came From: @Kip https://stackoverflow.com/a/4835406/7215091
function escapeHtml(text) {
var map = {
'&': '&',
'<': '<',
'>': '>',
'"': '"',
"'": '''
};
return text.replace(/[&<>"']/g, function(m) { return map[m]; });
}
var RegexTesterAddon_URL='link to a spreadsheet that contain defaults';
Spreadsheet Must have a page named Defaults and it looks like this:

The page only uses Columns A and B and it must have message,Regex,g,i,m and results as shown in the image. A typical setting for g,i,m is TRUE, FALSE, FALSE which will get you started. This Regex works for your current requirements <.*q=cats.*>