From 636d43e97eec71755092696b03a869cfc37248a9 Mon Sep 17 00:00:00 2001 From: stuzer05 Date: Thu, 7 Nov 2024 11:31:12 +0200 Subject: [PATCH] Commit --- .gitignore | 1 + composer.json | 4 ++-- easy_unsubscribe.css | 18 ++++++++------ easy_unsubscribe.php | 52 ++++++++++++++++++++++++++++++----------- icon.png | Bin 1062 -> 2051 bytes localization/en_US.inc | 1 - localization/es_ES.inc | 1 - localization/ru_RU.inc | 1 - 8 files changed, 53 insertions(+), 25 deletions(-) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..723ef36 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.idea \ No newline at end of file diff --git a/composer.json b/composer.json index 51d3149..528e8a5 100644 --- a/composer.json +++ b/composer.json @@ -1,10 +1,10 @@ { - "name": "ss88/easy_unsubscribe", + "name": "stuzer05/roundcube-easy-unsubscribe", "type": "roundcube-plugin", "description": "Displays a small icon after the subject line when viewing an email, so you can very quickly unsubscribe.", "license": "GPL-3.0+", "keywords": ["unsubscribe","subscription", "newsletter", "mailer"], - "homepage": "https://github.com/SS88UK/roundcube-easy-unsubscribe", + "homepage": "https://gitea.stuzer.link/stuzer05/roundcube-easy-unsubscribe", "require": { "roundcube/plugin-installer": ">=0.1.6" } diff --git a/easy_unsubscribe.css b/easy_unsubscribe.css index 44be9a4..0a96e72 100644 --- a/easy_unsubscribe.css +++ b/easy_unsubscribe.css @@ -1,8 +1,12 @@ -.easy_unsubscribe_link img { height: 13px; margin-left: 10px; vertical-align: middle; opacity: 0.5; transition:all 0.3s ease; } -.easy_unsubscribe_link:hover img { opacity:1; } +.easy_unsubscribe_link img { + height: 20px; + margin-left: 10px; + vertical-align: middle; + opacity: 0.5; + transition: all 0.3s ease; + cursor: pointer; +} -/** - * Tooltip Styles - */ - -.tooltip,[data-tooltip]{position:relative;cursor:pointer}.tooltip:after,.tooltip:before,[data-tooltip]:after,[data-tooltip]:before{position:absolute;visibility:hidden;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";filter:alpha(Opacity=0);opacity:0;-webkit-transition:opacity .2s ease-in-out,visibility .2s ease-in-out,-webkit-transform .2s cubic-bezier(.71,1.7,.77,1.24);-moz-transition:opacity .2s ease-in-out,visibility .2s ease-in-out,-moz-transform .2s cubic-bezier(.71,1.7,.77,1.24);transition:opacity .2s ease-in-out,visibility .2s ease-in-out,transform .2s cubic-bezier(.71,1.7,.77,1.24);-webkit-transform:translate3d(0,0,0);-moz-transform:translate3d(0,0,0);transform:translate3d(0,0,0);pointer-events:none}.tooltip:focus:after,.tooltip:focus:before,.tooltip:hover:after,.tooltip:hover:before,[data-tooltip]:focus:after,[data-tooltip]:focus:before,[data-tooltip]:hover:after,[data-tooltip]:hover:before{visibility:visible;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=100)";filter:alpha(Opacity=100);opacity:1}.tooltip:before,[data-tooltip]:before{z-index:1001;border:6px solid transparent;background:0 0;content:""}.tooltip:after,[data-tooltip]:after{z-index:1000;padding:5px 10px;width:160px;background-color:#000;background-color:hsla(0,0%,20%,.9);color:#fff;content:attr(data-tooltip);font-size:11px;line-height:11px}.tooltip-top:after,.tooltip-top:before,.tooltip:after,.tooltip:before,[data-tooltip]:after,[data-tooltip]:before{bottom:100%;left:50%}.tooltip-top:before,.tooltip:before,[data-tooltip]:before{margin-left:-6px;margin-bottom:-12px;border-top-color:#000;border-top-color:hsla(0,0%,20%,.9)}.tooltip-right:after,.tooltip-right:before{bottom:50%;left:100%}.tooltip-right:before{margin-bottom:0;margin-left:-12px;border-top-color:transparent;border-right-color:#000;border-right-color:hsla(0,0%,20%,.9)}.tooltip-right:focus:after,.tooltip-right:focus:before,.tooltip-right:hover:after,.tooltip-right:hover:before{-webkit-transform:translateX(12px);-moz-transform:translateX(12px);transform:translateX(12px)}.tooltip-left:before,.tooltip-right:before{top:3px}.tooltip-left:after,.tooltip-right:after{margin-left:0;margin-bottom:-10px} +.easy_unsubscribe_link:hover img { + opacity: 1; +} \ No newline at end of file diff --git a/easy_unsubscribe.php b/easy_unsubscribe.php index 33fbbd7..7690c08 100644 --- a/easy_unsubscribe.php +++ b/easy_unsubscribe.php @@ -7,6 +7,9 @@ class easy_unsubscribe extends rcube_plugin { private $unsubscribe_img; function init() { + ini_set('display_errors', '1'); + ini_set('display_startup_errors', '1'); + error_reporting(E_ALL); $rcmail = rcmail::get_instance(); $layout = $rcmail->config->get('layout'); @@ -20,41 +23,64 @@ class easy_unsubscribe extends rcube_plugin { $this->add_texts('localization/'); $rcmail->output->add_label('easy_unsubscribe.confirm'); - } public function storage_init($p) { - + $p['fetch_body'] = true; $p['fetch_headers'] = trim($p['fetch_headers'] . ' ' . strtoupper('List-Unsubscribe')); return $p; } - - public function message_headers($p) { - if($this->message_headers_done===false) { + public function decodeMimeHeader($header) { + $elements = imap_mime_header_decode($header); + + return array_reduce($elements, function ($carry, $element) { + return $carry . $element->text; + }, ''); + } + + public function extractUnsubscribeUrls($content) { + $pattern = '/https?:\/\/[^\s"\'<>]+\/[^\s"\'<>]*unsubscribe[^\s"\'<>]*/i'; + preg_match_all($pattern, $content, $matches); + return $matches[0]; + } + + + public function message_headers($p) { + if($this->message_headers_done === false) { $this->message_headers_done = true; if(!isset($p['headers']->others['list-unsubscribe'])) return $p; - - $ListUnsubscribe = $p['headers']->others['list-unsubscribe']; + $urls = []; + + $rcmail = rcmail::get_instance(); + $body = $rcmail->storage->get_body($p['uid']); + + $urls = array_merge($urls, $this->extractUnsubscribeUrls($body)); + + $ListUnsubscribe = $this->decodeMimeHeader($p['headers']->others['list-unsubscribe']); if (preg_match_all('/<(.+)>/mU', $ListUnsubscribe, $items, PREG_PATTERN_ORDER)) { - foreach ( $items[1] as $uri ) { - - $this->unsubscribe_img .= '' . $this->gettext('unsubscribe') . ''; - + $urls[] = $uri; } } + $urls = array_unique($urls); + + foreach ($urls as $uri) { + if (str_contains($uri, 'mailto')) continue; + if (!str_contains($uri, '?')) continue; + + $this->unsubscribe_img .= '' . $this->gettext('unsubscribe') . ''; + } + } if(isset($p['output']['subject'])) { - $p['output']['subject']['value'] = $p['output']['subject']['value'] . $this->unsubscribe_img; $p['output']['subject']['html'] = 1; - } return $p; diff --git a/icon.png b/icon.png index 934946750a2d89b309fd1a677bec9597f722672f..b662466c6b7de4982d7bf5332ea9b8066a39c665 100644 GIT binary patch literal 2051 zcmV+e2>kbnP)+^Lg_d*fD(};VwAw*9^AWt zM~<4L(}~8(Bn3KcA}Nj2!P;n$Tb5;Qv{BQ{q%*aKpk_!VF(Nk$3%mR7!S1@8743?A zJI@~Mvh3;$3fn*Y%{;>lGtB$>e4p?0zRwU8^kkmQlX)`#S5s1IK2%(4xm{9fK_FIf zspWR@N9Kb|7AP*YOa%(Q#4R!P2s;p1_!8$@vcMY$yIPA&&DKDH7aca=-uG7b@R9|j zuUtjp>#dgeey49+Y4`*0t7ozbuR)miEgnh0wcb3~bFKLB@}G&K56yV>SKSawzO}lCg z5*aWpHlSot0+M|W0kPyu0v`}?v6sXm1+E}(?-hvhz6?0L*tuv6xZv~lUbYJ)Hg!X! zyb~~Rp>Ae6_A9lPmVm1|1U`4qWe9Wsj_A(~h>`Umty#a~@Y~xbW+G*M;L5f1cEFWB zfzRF3;t;rCM)dg+L@HEBRCGf$WLy5!sr!ikCk0MzKX?iqxTg*D1YFf20y(=|AjokF z*dkE`cCk#nwAZIXV-ra+1LxNYzSP19$bY19K|98T<|%CMBodzzy&j+&YKZ= zR)@9qJxDy=1CjdPW9<5UY`Uler@9N=MvXmn7d)p)PgB5N9fv@6;WyZo{lz@^sBP0)LhWj9~3&M*DWNs=Ey96Or726 zfM>~c^aMQNv+|oA0`uTai1dKx{nZHGX#+TRi9WE7-@x<#pdixEJ`g^s)dEh{O|WbG z?0@Sobpp;LtAVaSp<5s`zZv|@^K;elOn>beD0HbCQjM^bE>(pSJqQI!9 zXbO<(6g1lfGNfN4E#tfc-Yb2cSNd!x1gp`J8hLm`MK{8Z-9XsUHZVT94t8ayqcRP{ z?$qTJm^J-ie%gtMzx;^sqt_5t{%_}ML)f3MBkYq7gr8K>6L6(Z;4>sd;M@bN<4E7D zv-T~g5K*f}_{jl;ecFf66MYD;^sI~?tl9xEPPBtn-ilY=t%qV?3EDIF!;~(?NV)_! zM6W`g|33B{r~%_oZ8QZ)b({iX$t8&LF8Qnu&#OB2-g@+vY}R+PW_ zF{T94hr*9-6JYGcU9i5upS32XmLcf(Px%$dls1=$rI)5%=?ioJ_3(r1T^+CV2|P(Z zq*8;`$GY*%N3A&WTG^uDM_=G$G${?%#Ft@BNGS_i%sg^+Tw;Ns{!OY+gW~c99 zT>82jJ}w#NXJ3SALsB*^0iNIVbv_QR*7w0ZK7eQb@Ezm@zgbY5$?UzDQ4NC(`8h5s zn1i?fZeR%3m&Ehn%^RPGX~R}IJpnrJ{0CHL%}F(akM-iGhp(Vr{F=|sPl)m{(?8$< zrgWGY*0|wQvV6cNVI*ctA1wi{LO->XcfJdLO@$i4<=uGtgBFaWOZ^_$@m=oJ?eIey zzwoA?C&Cz=K<~fUoYVSWvK59tj$Ef=H|kVOnNH1Y)Z3UcosH2z*&$6JU(o)VtyW6FbCB3*ZIw5A5j6 zS+MTRn3K5IKM3>IwE6JsH$lHHu5rZ$#Kel6o?_WN^&t9 z^|&5*f24eN-U+Yg#m?$D&(gn2EQ>@^+8>t!Z{Wp3$Jw~J%iMAdxe{9wQp)TXvqdGp zu?#^${;$(3J(l=np(QR^`OxIKvC4qg#@`?=ZWXzhnKmRfjl?AOk}s?wYV(wFeSD98 hZJeCEZTubB{{g`c8EiBRKn(x@002ovPDHLkV1i1P@>2i+ literal 1062 zcmV+>1ljwEP)T!wC}!5uhrAiuVT%g;^UaPiYVT#y!Jl|#+@G4ToW=vKk5mo%`E;-*l z0Nj|8^9p=j10KSoDPsDG03H{z20f4>7UNochqJM!T`6Yh~@oV zQ~etnWCQGHn1bE~XJJRld1=Y{(vtHVcpDd}9$iaP#5E~m*8r#8-_P;UYxlIb_g+a? zikL7M;F9w+yr2q&X88p7r-<(d@SlkJn28yxo3#lmQ^b~GfvguAp~}={^&)@c@f7j= z06wGe3>K5z3SPOXRQQ^YpRsXS%Pm#S>u-U!)mt29Izsk&=aHC&4L2D4S$dMY-RoM-nsq=?^DO-{n)jkSAR$+@?w z7_Kh8;0#B?>hO9gVtWntF~(wJ$$4&FiW_bJY0U0c$dVMXvQbfTo~&x&#;US@4z}ah z8uY<7RpWWEMUeNFoR7+bx~ZOt-&9%u9^S-g)w6VMDy1knpRekUPsZC~!G(CY9>1I- z?m5P&DwP{>afABd6tOCm(wf~aIX|T;p=y|=DPniS{1{dLc~`C4j%g{PyJe6y$Z9NV zQ0>58RXk2{b%707*qoM6N<$g5h`ai~s-t diff --git a/localization/en_US.inc b/localization/en_US.inc index ccdd683..9a7665a 100644 --- a/localization/en_US.inc +++ b/localization/en_US.inc @@ -2,6 +2,5 @@ $labels = array(); -$labels['click_to_unsubscribe'] = "Click to unsubscribe"; $labels['confirm'] = "Are you sure you want to unsubscribe?"; $labels['unsubscribe'] = "Unsubscribe"; diff --git a/localization/es_ES.inc b/localization/es_ES.inc index 29c45d4..0e5a113 100644 --- a/localization/es_ES.inc +++ b/localization/es_ES.inc @@ -2,6 +2,5 @@ $labels = array(); -$labels['click_to_unsubscribe'] = "Haz click para anular la suscripción"; $labels['confirm'] = "¿Estás seguro de que deseas anular la suscripción?"; $labels['unsubscribe'] = "Anular suscripción"; diff --git a/localization/ru_RU.inc b/localization/ru_RU.inc index 964f96c..aa797aa 100644 --- a/localization/ru_RU.inc +++ b/localization/ru_RU.inc @@ -2,6 +2,5 @@ $labels = array(); -$labels['click_to_unsubscribe'] = "Нажмите, чтобы отписаться"; $labels['confirm'] = "Вы уверены, что хотите отказаться от подписки?"; $labels['unsubscribe'] = "Отписаться";