Commit graph

7270 commits

Author SHA1 Message Date
Samuel Soriano
4e65e7ee84 Use the username label for login fields 2026-10-16 17:54:39 +02:00
Samuel Soriano
aca14765c9 Review Catalan terminology, grammar and action meanings 2026-10-16 17:53:07 +02:00
Samuel Soriano
be91e4eb80 Document the Catalan language selector preview 2026-10-16 16:20:42 +02:00
Samuel Soriano
24d7dee9b9 Add Catalan localization 2026-10-16 16:19:20 +02:00
Andreas Pries
6ef8a9a391 Fix duplicate contacts on autosave for addresses with uppercase letters
IncFrec() lowercases the existing addresses but compares them against the
new address in its original case, so an address with uppercase letters is
never found and a new contact is created on every send.

Fixes #1767
2026-09-29 22:48:07 +02:00
Fathi Ben Nasr
08ddc323f9 HtmlUtils: strip every data-* attribute, not just the first one
BuildHtml() iterates $oElement->attributes -- a live DOMNamedNodeMap --
and calls removeAttribute() on the attribute the foreach is currently on.
That ends the iteration: the loop sees no further attribute, so exactly
one data-* is removed per element however many it carries.

Measured on PHP 8.5.10 / libxml 2.12.5, data-* left behind:

  <p data-a>                          -> none
  <p data-a data-b>                   -> data-b
  <p data-a data-b data-c>            -> data-b, data-c
  <p data-a data-b data-c data-d>     -> data-b, data-c, data-d
  <p DATA-A data-b>                   -> data-b

The single call site is buildMessage() in RainLoop/Actions/Messages.php,
reached from both DoSaveMessage() and DoSendMessage(), as the docblock on
BuildHtml() says. So the attributes that survive go out in the sent
message and into the draft that is APPENDed and read back later. It is
not the display path: an incoming body is only decoded and charset
converted in MailSo\Mail\Message::fromFetchResponse(), and the browser
filters it with the allowlists in dev/Common/Html.js.

The fix collects the names first, then removes them.
2026-09-05 21:44:57 +00:00
Fathi Ben Nasr
279cc6406e PdoAddressBook: GetContactByEmail() passed the wrong columns
GetContactByEmail() runs

    SELECT DISTINCT id_contact FROM rainloop_ab_properties WHERE ...

and hands the statement to getContactsFromPDO(), which unconditionally reads
id_contact_str, changed, etag and jcard from every row. None of those are
selected, so every match raises three PHP warnings:

    Undefined array key "id_contact_str"
    Undefined array key "changed"
    Undefined array key "etag"

and the Contact that comes back carries IdContactStr '' with Changed and Etag
both 0 -- values a CardDAV sync would use.

The lookup itself still works: with no jcard column either, every row falls
into the follow-up properties query, so the contact data is right and only the
metadata is wrong. That is what makes it easy to miss.

It is not rare. The avatars plugin calls GetContactByEmail() for the sender of
a message, so a mailbox view triggers it repeatedly -- 23 warnings in a single
session on one of our installs.

Fix: look the contact up by id instead. GetContactByID() already selects the
columns getContactsFromPDO() expects, so the Contact comes back complete, and
the search query keeps doing what it is good at -- finding the id. The unused
$oContact and $iIdContact locals go with it.

Verified against a real PDO: the current query returns one column and the
reader warns on id_contact_str; the replacement returns all of them, warns
nothing, and yields the real IdContactStr and changed instead of '' and 0.

Note: this layer has no test suite upstream, so the verification is a
standalone reproduction rather than an added test.
2026-09-05 03:37:09 +00:00
Fathi Ben Nasr
3dd6c85c87 ldap-contacts-suggestions: search several base DNs
A directory rarely keeps everything worth suggesting in one branch: people
sit in a people branch, meeting rooms and other bookable resources in a
separate one. Searching a single subtree misses them, and widening the base
to the domain root drags every service and role account into the list.

base_dn now accepts several branches separated by '|', which cannot appear
unescaped in a DN — an existing single-branch value parses to a one-element
list and behaves exactly as before. A branch that fails to answer is logged
with its own DN and no longer discards the whole lookup.
2026-08-24 01:20:24 +00:00
SebaSalvaG
e4ecda0e61 Don't reset the message list to page 1 and clear the search on message.show
The `mailbox.message.show` handler rewrote the hash to `mailBox(sFolder)` --
page 1, no search -- even when the user was already in that folder.

Because the hash of an open message carries the message id and the new one does
not, the two differ, the route fires again, the message is shown again, and the
handler runs again: a loop. Every iteration aborts whatever message list request
was pending, so browsing to page 2 or running a search silently bounces back to
page 1 of the INBOX with an empty search box.

Only navigate when we are not already in that folder. Clicking a new-mail
notification from another folder still takes you to the INBOX; if the message is
not in the current page, the else branch already opens it in the preview pane
without touching the list.

The same unconditional setHash a few lines below, for non-INBOX folders, gets
the same guard.
2026-08-23 22:38:40 +02:00
Rong Zhou
640c567210 Admin panel: accept trusted proxy-auth header (X-NC-Admin) on the admin host
Allows gating the SnappyMail admin panel behind an external single sign-on
layer (e.g. a reverse-proxy auth_request validated against an OpenID Connect /
Nextcloud session) without embedding an OIDC client in SnappyMail. The header
is honored only when present AND the request Host matches admin_panel.host
(defense in depth), so it has no effect on regular webmail or on the panel
when admin_panel.host is unset.

Behavior is unchanged when the header is absent: the existing
admin_login/admin_password (+ optional admin_totp) check applies.

Contributed from Ron-RONZZ-org/ronzz-nextcloud (webmail/patches/).
2026-08-16 18:17:08 +02:00
Fathi Ben Nasr
8a2d8e86a5 ics-viewer: unwrap attachments and widen the calendar part match
The panel never appears on a real invitation.

msg.attachments is a ko.observableArray, so msg.attachments.find() is
undefined and throws inside the message subscription - the rest of the
handler, including the JSON-LD path, dies with it. The app itself always
writes attachments().

A scheduling mail also does not necessarily carry a text/calendar
attachment. Evolution and Exchange put the scheduling part inline in
multipart/alternative as text/calendar and repeat it as an
application/ics attachment, so such a message shows two .ics files and
the current test matches neither reliably. Match text/calendar,
application/ics, text/x-vcalendar or an .ics file name - which is what
the commented-out line above was reaching for.
2026-08-14 10:12:06 +00:00
Fathi Ben Nasr
6a7cbe070c avatars: find the photo when several contacts share an address 2026-08-13 02:19:03 +00:00
Fathi Ben Nasr
1a0c9872b2 AddressBook: do not let an empty side wipe the other during sync
Sync() treats an empty list on either side as authoritative:

* a local contact holding an etag but missing from the remote listing is
  deleted locally, so an empty or unparsed listing removes every
  previously synced contact;
* a local tombstone is deleted remotely, so a local store that is empty
  apart from tombstones prunes the server.

An empty list is far more often a fault than a real "delete everything":
a fresh or rebuilt local store, a listing that failed to parse, a stale
server-side index. On a server whose DAV index had lost its records the
listing came back empty and the first sync removed 7 local contacts that
existed on both sides moments earlier.

Skip the deletions in whichever direction the source list is empty and
let the existing import/export reconcile instead. Both guards log a
warning with the counts, so a skipped pass is visible rather than silent.
When both sides hold data the behaviour is unchanged.
2026-08-12 23:38:53 +00:00
Philipp Mundhenk
863f719da3 proxy-auth: remove check_proxy / proxy_ip settings
The "Check Proxy" option inspected the forwarded client IP returned
by Http::GetClientIp(true), which resolves to HTTP_X_FORWARDED_FOR
first and only falls back to REMOTE_ADDR. In any typical reverse-proxy
deployment that header carries the end-user's IP, not the proxy's, so
the option never actually validated that the request came from the
trusted proxy. It only constrained the set of end-user IPs allowed
to use SSO, which is not a meaningful guarantee on its own.

Drop the option, the paired proxy_ip subnet field, and the
ip_in_range helper. Document that access must be gated at the
network layer (firewall / docker network / bound interface) and
that the upstream proxy must strip any client-supplied value of
the configured remote-user header.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-17 10:44:36 +02:00
Philipp Mundhenk
68588287ef proxy-auth: document APP_SALT rotation troubleshooting
Add README note explaining that AUTHENTICATIONFAILED after a
container rebuild or data reset is typically caused by an
APP_SALT change invalidating the encrypted master credentials,
and that re-entering them in the admin UI restores access.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-17 09:57:22 +02:00
Philipp Mundhenk
60ee74c68a proxy-auth: fix check_proxy enforcement and persistence
The proxy IP check was never enforced: ServiceProxyAuth read config
key 'proxy_check' but the property is registered as 'check_proxy',
so the lookup always returned the default empty string and the
else-branch set $sProxyRequest = true unconditionally.

The BOOL property also had SetEncrypted(), which caused getDecrypted()
to call DecryptFromJSON() on a literal bool and fail with
"DecryptFromJSON() invalid $data", so the admin UI never reflected
the saved value. BOOLs are stored as plain bools in JSON; switch to
Get() and drop SetEncrypted() on the property.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-17 09:54:54 +02:00
Philipp Mundhenk
ed35c8e91e
Merge branch 'the-djmaze:master' into master 2026-05-17 09:47:52 +02:00
alexgabi
f757d58534
Update user.json
Rewieved and completed basque translation
2026-05-04 13:11:34 +02:00
the-djmaze
c154d23cfe Ommit Nextcloud "max-version" as it is optional 2026-03-11 17:56:44 +01:00
Till Wimmer
c1f1faca58 FIX non-compliant Autocrypt Header 2026-02-13 02:06:33 +01:00
Super User
dc0191aaf1 Add HTTP based SSO plugin for Apache using PHP_AUTH_USER/PHP_AUTH_PW 2026-02-09 19:47:30 +00:00
bohwaz
a8117a9d03 Fix login-remote plugin password handling 2026-01-06 00:04:41 +01:00
oGrzegorZo
f2648a54c0
Fix Search Filters plugin: crash on keyword filters
Fix Search Filters plugin: crash on keyword filters

- Added try/catch in searchMessages() to prevent fatal IMAP errors.  
- Correctly handle keyword filters ($label1, $label2) with multi-folder search.  
- Extracted applyActions() to handle fSeen/fFlag/fFolder consistently.  
- Ensures plugin no longer crashes when messages exist with a tag.
2025-12-16 14:19:30 +01:00
Jürgen Schlegelmilch
1dc26f11d2 fixed typo in imapsync.php: was "RainLoop\API" instead of "RainLoop\Api" 2025-11-19 23:10:15 +01:00
juschleg
c203d15b17
Update SSLContext.php: fixed typo in line 42, to reference correct class
The reference to class RainLoop\API is invalid, the author obviously meant class RainLoop\Api
2025-11-15 23:12:25 +01:00
Avinash Gusain
2c54ac9be3 Fix(auth): Correct OIDC login by using SensitiveString object. 2025-11-12 14:41:47 +05:30
Manuel
2c73a955e2
Update PostgreSQL DSN in Docker.md
docker compose file defines network as db not postgres
2025-11-09 20:00:39 +01:00
HeySora
658b97f5b4
Add pdo_sqlite installation to Docker image 2025-07-16 12:50:18 +02:00
the-djmaze
ba496919dd Catch Throwable for #1914 2025-06-16 17:35:11 +02:00
Maarten
24bb509b96
Merge pull request #1914 from sgoranov/fix/1913-datetime-overflow
Fix DateTimeHelper::ParseRFC2822DateString integer overflow on 32-bit PHP
2025-06-16 17:30:55 +02:00
Maarten
56409dcbb4
Merge branch 'master' into pgp-improvements 2025-06-16 17:28:39 +02:00
Maarten
b4a6068d5b
Merge pull request #1875 from bapt/fr
fr: add an space before the colon
2025-06-16 17:26:21 +02:00
Maarten
40cf2b950e
Merge pull request #1931 from TLTDevRu/fix-ru-lang
Fix ru lang
2025-06-16 17:23:27 +02:00
Maarten
7397a95a7c
Merge pull request #1941 from bober757/master
incorrect using of the preposition
2025-06-16 17:22:21 +02:00
the-djmaze
9dd7c021fd Small change for #1948 to make it relative to font size 2025-06-16 17:21:26 +02:00
Maarten
9f6d2e4cb7
Merge pull request #1948 from makoehr/compact-folder-list-for-snappymail
More compact view of folder list
2025-06-16 17:19:20 +02:00
Maarten
93e3c431ec
Merge pull request #1961 from Psychi1/Cp1252
Fix the Cp1252 encoding problem
2025-06-16 17:03:26 +02:00
Philipp Mundhenk
a9b89fd7b3
Update instructions for Dovecot 2.4 2025-06-07 13:06:23 +02:00
Psychi
da96945f39
fix regex match-group 2025-05-25 21:13:55 +02:00
Psychi
0bc9950b42
Fix Cp1252 encoding 2025-05-25 21:04:40 +02:00
Mathias Koehrer
c3660bee57 More compact view of folder list
With many folders, the line-height is too large.
It is reduced to make the view more compact.
Also, the top margin for the number of unread-folder will
be adapted.
2025-04-11 17:19:19 +02:00
the-djmaze
dea7f4d1d8 openssl_pkey_free is deprecated 2025-04-04 23:52:27 +02:00
6o6ep
00128e837f
incorrect using of the preposition 2025-04-02 10:22:23 +03:00
6o6ep
d9eaad24ad
incorrect using of the preposition 2025-04-02 10:21:05 +03:00
Roman Chutchev
9565559213
Update user.json 2025-03-11 23:10:42 +02:00
Roman Chutchev
1c9c9f0d6b
Merge branch 'the-djmaze:master' into fix-ru-lang 2025-03-11 22:37:35 +02:00
Maarten
d3b120bbe7
Merge pull request #1880 from tribut/i18n-de-fixes
Fix incorrect German translation
2025-03-10 16:45:38 +01:00
Maarten
a024d34f6d
Merge pull request #1891 from HeySora/master
Automatically add favicon host to CSP if present
2025-03-10 16:43:35 +01:00
the-djmaze
33fbaa9598 Bump version for #1918 2025-03-10 16:35:27 +01:00
Maarten
86da00eb50
Merge pull request #1918 from TomsProject/master
Changing Gravatar hashing algorithm to sha256
2025-03-10 16:34:17 +01:00