Changelog
Was ist neu?
Jede Verbesserung an der Plattform, wie sie geliefert wird.
· EmailService
DKIM-Schlüssel und ein entspannter/entspannter rsa-sha256-Schilder für Organisationen, die Domains senden
DkimKeys generiert den RSA-2048-Schlüssel einer Domain (im verschlüsselten Bulk-Provider-Blob der org) und der TXT -Wert veröffentlicht ein Mitglied unter kamoXXXXXX._domainkey.<domain>. DkimSigner signiert eine Anzeige genau wie die transport sendet es - lesen Sie von writeTo nach dem finalen saveChanges - Abdeckung Von und welche von die Header-Empfänger und Feedback-Loops vorhanden sind (Feedback-ID enthalten, nie ein X-Header, da die Relaisstreifen X-Kamo-Ref). Verifiziert in Tests von Apache jDKIM, eine unabhängige Implementierung: eine Kampagne- die Botschaft überprüft, überprüft noch, sobald das Relais X-Kamo-Ref abstreift und an einem veränderten Körper versagt oder Thema.
· EmailService
DNS zum Senden von Domains - die eigenen Nameserver jeder Domain zuerst, SPF ausgewertet, DNS-Provider benannt
LiveDnsResolver fragt die maßgeblichen Namenserver der Zone (gefunden durch 1.1.1.1/8.8.8.8), also einen Datensatz Mitglied, das gerade bei ihrem DNS-Provider gespeichert wird, wird auf einmal gesehen und nicht nach dem negativen Cache eines Rechenwagens verfällt; es fällt zurück zu den öffentlichen Resolvern auf eine Empfehlung oder eine Auszeit, und retries über TCP, wenn ein Die Antwort passt nicht zu einem Datagramm (dnsjava 3.5 scheitert an parse google.com's abgeschnitten TXT and otherwise). SpfEvaluator bewertet die Richtlinien einer Domain für eine IPv4-Adresse, wie es ein Empfangsserver wäre (RFC 7208: ************ umgeleitet, die 10-Look-up- und 2-void-lookup-Limits), also eine CNAME contact.kamocrm.com, ein include oder ein nackter ip4 liest das Gleiche. DnsProviders benennt das Unternehmen, das läuft Das DNS einer Zone von seinen Nameservern, für Anbieter-spezifische Anweisungen.
· EmailService
Die gemeinsame Org-Relais (47.181.8.86) ist für jede Organisation ausgesät; die Plattform-Staffel bleibt KamoCRM's
PlatformRelayProperties kennt jetzt beide In-Cluster-Relais: postfix-bulk (47.181.8.87, hello.kamocrm.com) und postfix-Orgs (47.181.8.86), mit der Egress-Adresse, DKIM-Auswahl und den DNS-Zielorganisationen' Senden von Domains CNAME an (contact.kamocrm.com). Beide zählen als Relais, so dass beide Lieferberichte erhalten. Der Startup Backfill Samen k3m1-org-rel als SHARED Plattform Host (STARTTLS + PLAIN Anmeldung von der optional Secret Bulk-Or-Relay-auth, selbst signiert, so tlsVerify ausgeschaltet), abgeschaltet in KamoCRMs eigener Rotation so bleibt seine E-Mail auf .87; ausgesät, bis ein Anmelde-in konfiguriert ist, und seine Anmeldeinformationen folgen config auf jeder Start. k3m1-bulk-Relay wird PLATFORM_ONLY einmal gemacht.
· KlusterServices
Postfix-Orgis, die gemeinsame Massenrelais, die jede Organisation sendet, mit 47.181.8.86
KamoCRMs eigene Kampagnenpost geht immer wieder über Postfix-Bulk (47.181.8.87) und reguläre Post durch postfix (47.181.8.84). Jede andere Organisation Kampagne Mail bekommt eine eigene IP: postfix-orgs läuft auf k3m1's Host-Netzwerk und bindet seine ausgehende SMTP an eno1 (k3m1-ext), welche Knoten-Konfiguration/k3m1-ext-Routen aus diesem Port und nichts anderes verwendet. HELO ist contact.kamocrm.com, der Name Frontier setzt als die IP's PTR. Ein hostNetwork-Hörer hat keine NetworkPolicy, so dass die Einreichung SASL über erforderlich STARTTLS auf Port 587 von die interne Adresse des Knotens, nur von Clusteradressen (secrets in mail/SECRETS.md). Es gibt nur als die Senden Domains EmailService hat jede Minute überprüft, aktualisiert jede Minute - bis diese Karte ankommt, nichts. Derselbe Austrittsschutz wie Postfix-Bulk hält die Lieferung, bis eno1 als .86 und der gleiche Liefer-Events Sidecar berichtet Ergebnisse. Jede Verweigerung ist ein 4xx, nie ein 5xx. An die Dateien an die Dateien anhängen, gilt der Einsatz-Workflow bereits, so dass der Workflow (und eine vollständige Versöhnung von Jede Komponente) ist unberührt.
· kamo-internal
Die Kampagnen-Tabs erhalten Scroll-Pfeile zurück, ohne die ausgewählte Registerkarte zu verstecken
Auf einem Bildschirm zu schmal für die fünf Sub-Tabs, der Streifen zeigt jetzt links und rechts Pfeile daneben, wie es der maximierte Fensterabentreifung tut. Es hatte keine seit dem erste Version, wo MUI "Auto" Scroll-Tasten schneiden Sie einen Tab durch Link geöffnet (?tab=archiviert) in der Hälfte: sie erscheinen erst, nachdem MUI die ausgewählten gescrollt hat tab in Sicht, nehmen Sie 80px aus dem Streifen, und MUI eigene Scroll-Animation dann Überschrieben jede Korrektur. CampaignTabStrip setzt die Tabs in einem einfachen Scroller ohne eigene Bar (data-kamo-scrollbar="off"), zeigt die Pfeile nur während der Tabs überlaufen, und scrollt die ausgewählte Registerkarte wieder in Sicht, wenn sie sich ändert und wann Pfeile kommen oder gehen ändert die Breite. arrowState und ARROW_SCROLL_FRACTION kommen von maximizedTabStripModel, so dass beide Streifen vereinbaren, wenn ein Pfeil ist live und wie weit es geht. Überprüft in Chrome: bei 1600px keine Pfeile; bei 700px und 520px jeder Registerkarte von geöffnet Link ist vollständig sichtbar mit dem Indikator unter ihm, einschließlich der mittleren; die Pfeile Seite der Streifen jeden Weg; ArrowRight bewegt Fokus entlang der Registerkarten und hält den fokussierten Tab in Sicht, und Enter wählt ihn aus. Seine Pfeile Etiketten sind components.scroll's, von Hand in jedem Ort in repariert kamo-translation-dictionary cc484906 (Arabisch hatte es "verdammt" für Scroll rechts). Vitest Rote hier sind nicht von dieser Änderung und scheitern identisch auf Haupt: oneScrollbar.test.ts (auf NavTopMenuPanel.tsx) und repressStatus.test.ts (4, hin und herging 98156e52).
· kamo-internal
Ein Live-Sende in der E-Mail-Kampagnen Widget bekommt eine Scheinwerfer-Karte
Mit einem Senden in Fortschritt, die In-Progress-Tab war eine einzige dünne Zeile in einem mit Raum für weit mehr, im Moment ist das Widget am meisten zählt. Wann jede Kampagne auf einer Registerkarte sendet oder pausiert, und das Panel gibt jede an Am wenigsten seine minimale Höhe, jeder bekommt jetzt eine Karte: - wie weit durch die Liste ist es, in einer großen Zahl abgerundet, so dass es sagt nie 100% mit etwas übrig; - seine Spur bei 10px, der Kopf und der Glanz sichtbar; - Tempo und Zeit übrig, und "N von insgesamt"; - geliefert, geöffnet, geklickt und geprallt, als Trichter neben dem Tempo Diagramm auf einer Karte mit Höhe zu ersparen (wahre Barlängen und Preise), oder als eine Reihe von Zahlen auf einer kürzeren oder schmaleren Reihe; - sein Tempo in den letzten 5 Minuten, eine Bar pro 15 Sekunden auf der Uhr selbst Grenzen. Die Bar noch füllen ist beleuchtet, und die Zeit, bevor die Scheibe sah die Senden ist ein Stub, nicht eine Null. Die Karte hat den Link der Reihe und Pause/Reume (beide jetzt geteilt, von CampaignRow). Es hält durch das Ziel, das es feiert. Zwei Senden sitzen Seite nebeneinander in einer breiten Scheibe. Die Wahl liest nur die Größe des Panels, die nichts in ihm ändern kann, so kann es nicht flimmern. Eine Karte, die sowieso überläuft, wird dafür in Erinnerung bleiben Panelgröße, die dann Zeilen anzeigt. Die Layouts innerhalb der Karte sind Container-Abfragen nach der eigenen Größe der Karte. Modell: PaceBuckets verbreitet, was sich zwischen zwei Frames im Laufe der Zeit bewegt zwischen ihnen. drückenSample nimmt ein Fenster, und der Haken hält fünf Minuten pro live senden, durch eine Pause und ein Ende. Geprüft kopflos auf einer 10-fachen Uhr mit unterschiedlichem Tempo, in regelmäßigen, breiten, hohe, 460 und 668x420 Panen, und mit zwei Senden in den breiten und hohen Scheiben: Karten passen ohne Überlauf, und die Pace Bars folgen den Rahmen, einschließlich eine ruhige Strecke. Nichts bewegt sich unter reduzierter Bewegung.
· kamo-internal
E-Mail-Kampagnen Widget-Tabs sind die Kampagnen-Bildschirm-Stadien
Das Widget eingereicht Kampagnen unter seinen eigenen Live / Sent / Drafts, die eine abgesagt Kampagne unter Sent und eine geplante unter Live. Seine Tabs sind jetzt In-Progress, nicht gestartet, Paused und Complete, eingereicht von KampagneTabOf und benannt mit marketing.bulkEmail.tabs.*, also die Launchpad und /marketing/email nie legte eine Kampagne an zwei Stellen. Die Zähler kommen von den neuen "Stagesen" von EmailService (7481f15); die Antwort eines älteren Servers wird von den gesendeten Kampagnen gezählt. Die Wahl der Registerkarte: - Bis das Mitglied eine auswählt, landet die Schelee auf dem, was geschieht und bleibt während dieser Tab noch etwas hält. Es bewegt sich nur, um eine senden, dass nur zeigen gestartet, oder wenn die eigene Registerkarte ausläuft. Ein Senden, das gerade fertig hält In-Progress für seine Feier, dann geht die Schehle weiter. - Eine Reihe, die das Mitglied pausiert oder wieder bleibt, wo sie es gedrückt, mit seiner Wiederaufnahme, bis sie die Registerkarte verlassen. - Bühnennamen zeigen, wo sie neben "N mehr" passen, gemessen an einem versteckten Kopie in der Sprache des Mitglieds; sonst zeigt jede Stufe ihr Symbol, mit der Name in seinem Tooltip und zugänglichen Namen. Korrekturen beim Checken im Browser gefunden: - Funken von neuen Öffnungen und Klicks auf eine fertige Kampagne waren nie sichtbar: die Zahlen Linie schnitt sie. Es schneidet jetzt nur unter und außer sich, und die Funken fliegen vom Ende des Meters, so dass sie die Stangen fallen überleben. - Eine Reihe zu schmal für seine Zahlen zog die geöffnete Meter über Clicked. Die Bars gehen zuerst unter 340px, und alles, was noch nicht passt, wickelt sich ein des Sehens ganz. - Eine KPI-Fliese zu schmal für ihren Namen und die Rate ellipsend den Namen ("Ope..."). Die Rate wickelt sich nun aus den Augen statt. - "N mehr" zählte die Zeilen beim Verlassen des vorherigen Tabs. Bei den Panebreiten 322 bis 1360 kopflos überprüft: kein Zeilenschnitt, kein Tab-Überlauf, Namen/Ixons-Schalter mit und ohne "N mehr", Pfeiltasten, eine Oberfläche dann gehalten zog weiter, und Funken unclipped bei 668 und 460. Der Server des Pausentests jetzt antwortet mit der pausierten Kampagne. Es scheiterte unter Last, wenn das Widget ist 400ms nach einer Pause zurückgelesene 400ms nach einer Pause, die die Kampagne noch senden würde.
· EmailService
Die Kampagnen Widget liest sich nach Bühne, die Stufen der Kampagnen Bildschirm-Dateien von
Das Launchpad Widget liest jetzt Gruppen und zählt Kampagnen von den Stufen /marketing/email's Tabs Verwendung: In-Progress (Senden), nicht gestartet (Entwurf oder geplant), Pause (Pause oder abgesagt), Komplett (sent). Gesche Dabei gefasste Dateien von how weit seine senden bekam, wie KampagneTabOf gibt. Jede Etappe ist für sich geschlossen: vor Entwürfen und frühestens zuerst geplant; pausiert, bevor abgesagt. "stages" wird neben "Gruppen" hinzugefügt, die bleibt, bis kein Widget-Build, das liest es wird eingesetzt. Zuvor zählte eine abgesagte Kampagne als fertig, die wo der Benutzer heute entschieden hat, dass er nicht dazugehört.
· kamo-internal
Die Kampagnen-Liste folgt, was Kollegen tun, um eine Kampagne, live
BulkEmailWorkspace nimmt die Änderungsrahmen mitEmailCampaignsWebSocket jetzt liefert (aufChanged, d0b56adf). Ein Rahmen benennt eine Kampagne und was damit passiert ist, nie die Kampagne selbst, so liest die Liste, dass eine Kampagne wieder durch GET /campaigns/{id' und setzt es an Ort und Stelle. Archiv eines Kollegen oder Wiederherstellung bewegt die Reihe zwischen den Registerkarten hier, wie es geschieht, erscheint eine neue oder duplizierte Kampagne, und eine gelöschte, oder eine, die jetzt beantwortet 404, verlässt die Liste. Die inszenierte Die Austrittszahl folgt den gleichen Frames. erstellenCampaignChangeFollower hält eine Lesung pro Kampagne zu einer Zeit. Rahmen, die kommen, während eine Kampagne gelesen wird (eine Liste in Scheiben hochgeladen kündigt jede Scheibe) fragen Sie nach einem weiteren Lesen, sobald es zurückkehrt, so dass ein Burst kostet zwei liest und ein Die ältere Antwort landet nie auf einer neueren. Eine Kampagne gelöscht, während seine lesen war auf dem Weg ist nicht zurückgesetzt, wenn es zurückkehrt. In Chrome gegen die reale Komponente durch Drücken von Frames durch den Haken überprüft: eine Wiederherstellung bewegt die Zeile aus Archived mit einem gelesen, ein Lösch entfernt seine Zeile mit keiner, erschien ein erstellter Entwurf unter nicht begonnen, und fünf Frames für einen Kampagne kostete zwei Lesungen.
· kamo-internal
Das E-Mail Kampagnen Widget, live auf der Startrampe
Ein neues Home-Widget, email.campaigns, auf der Startrampe von jedem, der öffnen kann die Kampagnen. Seine fünf Rechte (EMAIL_CAMPAIGNS_WIDGET, 321-325) hängen ab VIEW_BULK_EMAIL und ADDED, OPTIONAL und MOVABLE Samen von ihm in SecurityService, so kommt es an und ist das Mitglied zu entfernen. Auch das Tor fragt nach der Marketing-App und VIEW_BULK_EMAIL selbst. Was es zeigt, das neue /api/email/widget/campaigns von EmailService einmal lesen und danach live bewegen: - Vier Zahlen für die letzten zwei Wochen (geschickt, öffnet, Klicks, Bounces), jede mit eine Bar pro Tag, die von Mauszeiger oder Pfeiltasten liest, und öffnen und klicken Sie Preise aus der zugestellten Post nach der Regel, die die Lieferbarkeitskarte verwendet (engagementRate, jetzt geteilt von beiden). - Live / Geendet / Drafts, mit Zählungen. Eine Entsende-Kampagne ist eine Spur, die sich bewegt, mit seinem Tempo und Zeit links; öffnet und Klicks steigen aus ihm, wie sie landen. A Innehalten sagt man, warum es nicht senden kann; ein geplantes Counter-Punkte-Dok. zeigt seine Öffnungs- und Klickraten an. Pause und Lebenslauf sitzen auf der Reihe für ein Mitglied mit MANAGE_BULK_EMAIL. - Eine Kampagne, die endet, während die Pane Uhren bleibt auf Live für seinen Moment, mit einem Ausbruch, bevor er nach Sent bewegt. - Die Quintessenz trägt die Nachrichten, wie es geschieht; eine breite Palette hält es in einem Spalte mit den heutigen Summen. - Es legt für seinen Raum: zwei Figuren und kompakte Reihen an einer Säule, ganze Zeilen nur in jeder Höhe (die Liste wickelt sich statt Schnitte), und zwei Spalten von Kampagnen in einer breiten Fläche nur einmal, wenn man einige verstecken würde. Die Live-Halbrittfahrten /topic/campaigns/<orgId. verwenden Sie MailCampaignsWebSocket liest jeder Frame durch readCampaignFrame und Gewinne aufEngagement, on Changed und aufSnapshot, plus requestSnapshot, die das Widget ausschaltet, so dass ein Launchpad fragt nie die ganze Organisation für einen Schnappschuss. aufProgress sieht immer noch nur Fortschrittsrahmen. Das Schlussläut feuert jetzt auf einen Übergang in SENT, nicht auf jeder spätere Rahmen, der immer noch sagt SENT (späte Bounce und Lieferung Berichte neu veröffentlichen es für Stunden), und der Haken nicht mehr schreibt seine Handler ref während bildgeben. Verifiziert mit tsc, den Wach-Skripten, den neuen und betroffenen vitest-Dateien und einem kopfloser Gurt über die reale Komponente mit 1x1, 2x1, 2x2, 2x3 und voller Breite.
· kamo-internal
In-Progress, Not Started, Paused, Komplette und Archivierte Tabs, und die . öffnet seine Speisekarte
/marketing/E-Mail teilt die Kampagnen in fünf Sub-Tabs auf, jede mit einer Live-Zählung, und jede Kampagne ist genau unter einer: - In-Progress: Senden - Nicht gestartet: Entwürfe und geplante Kampagnen - Pause: Pausen und abgesagte Kampagnen - Komplett: gesendet - Archiviert: was auch immer ein Mitglied archiviert Gescheckt ist keine eigene Etappe: Empfänger scheitern, eine Kampagne nicht, und EmailService setzt es nie. Eine Kampagne, die es hat, wird eingereicht, wie weit seine senden bekam. Der Tab lebt in ?tab=, also ein Reload, der Zurück-Button und ein gemeinsamer Link halten es; eine Kampagne ändert Registerkarte von selbst, wie sein Status ändert sich live; und eine leere tab sagt, wofür es ist. Archiv und Wiederherstellung befinden sich im Menü der Kampagnen (E-Mail-Service 39ffa54). Nur ein Kampagne mit nichts zu senden kann archiviert werden: ein Entwurf, oder ein gesendet oder stornierte eine. Die Schaltfläche "" öffnete die Kampagne sowie das Menü. AG Grid feuert rowClicked von seinem eigenen nativen Hörer auf dem Zeilencontainer, der vor React's läuft delegiert aufClick, so dass die Stop-Propagierung des Zellengebers zu spät kam und die Zeile navigiert zum Editor unter dem Menü. Der Reihenhandler lässt jetzt durch klickt in einer Daten-Kampagne-eigene-Klick-Steuerung, wie es das Tracking Codes Grid tut, und ein Klick auf den Namen der Kampagne schiebt die Editor-Route nicht mehr zweimal. In Chrome gegen die eigentliche Komponente überprüft: auf Herkunft / Haupt-klick ging zu ************ mit dieser Änderung öffnet es das Menü und geht nirgends. Tabs, Zählungen, Archivieren und Wiederherstellen, leere Tabs und ein 520px Streifen waren auf die gleiche Weise überprüft. Der Wortlaut ist in kamo-translation-dictionary 02109cfc, zuerst geschoben und geschrieben von Hand in jedem Ort.
· EmailService
Archivieren Sie eine Kampagne, und das Widget lässt archivierte heraus
POST ************ und /unarchive (MANAGE_BULK_EMAIL) Set und klären Sie die Kampagne archiviertAt, und CampaignDTO trägt es. Die /marketing/email eine archivierte Kampagne unter eigener Registerkarte Archivdateien. - Nur eine Kampagne mit nichts zu senden kann archiviert werden. Eine geplante, senden oder angehalten wird einer abgelehnt: zuerst absagen. Das Archivieren behält das erste Date. - Jetzt senden, Termine und Senden Sie an die neuesten Clear archiviert ist wieder auf den funktionierenden Tabs. - Beide werden als ARCHIVED / UNARCHIVED Änderung Rahmen angekündigt, so dass jede offene Kampagnen Bildschirm und das Home-Widget-Update live. - CampaignWidgetReads lässt archivierte Kampagnen aus den letzten, inStatuss und KreisByStatus. Baut auf Kamo-Shared-Bibliothek ebdd15f1 **************** und der archivd_at Spalte, beide bereits vorhanden. TransactionalSendRatchetTest war rot auf Haupt vor dieser Übergabe und ist es immer noch; nichts hier berührt sendToUser. Die anderen 1554 Tests bestehen.
· kamo-shared-library
Eine Kampagne kann archiviert werden
EmailCampaignEntity gewinnt archiviert (archiviert_at): wenn ein Mitglied die Kampagne, null, solange es nicht ist. Der /marketing/E-Mail-Bildschirm bekommt einen archivierten Tab und das Home-Widget lässt archivierte Kampagnen heraus. Die Spalte befindet sich bereits auf dem Cluster, von Hand aufgetragen, da jede Schemaänderung ist: ALTER TABLE email_campaign.email_campaigns ADD COLUMN IF NOT EXISTS archived_at timestamp(6) mit Zeitzone; Nullable ohne Standard, wie die anderen Instants auf dem Tisch, so Code gebaut bevor diese Commit die Tabelle unverändert liest.
· EmailService
Eine Live-Lesung und Live-Frames für die E-Mail-Kampagnen home Widget
GET /api/email/widget/campaigns ist das Launchpad Widget eine gelesene, für eine Pane, die auf jeder Kampagne Zuschauer-Homepage sitzt den ganzen Tag: schlanke Reihen mit nein body (CampaignLine), Live-Kampagnen zuerst (senden, pausiert, am nächsten:) dann die zuletzt fertigen und die zuletzt bearbeiteten Entwürfe, jede Gruppe gedeckelt; genaue Zählungen pro Gruppe; jede gezeigte Kampagne öffnet, klickt und Relais-Berichte in einem Pipeline Redis lesen; die Organisation der letzten vierzehn Tage; seine Tracking-Wahl; und die Server-Uhr für Countdowns. Es braucht VIEW_BULK_EMAIL, wie es die Kampagnenliste tut. Drei Arten von Rahmen fahren jetzt /topisch/Kampagnen/<orgId" neben Fortschritt: - Engagement: CampaignEngagementPulse koutiert zuerst geöffnet, erste Klicks und Relais berichtet pro Kampagne und sendet höchstens ein Frame pro Sekunde pro pod, mit dem, was neu ist, da der letzte Rahmen und die Summen wie Redis hält sie. - geändert: CampaignController kündigt das Erstellen, Bearbeiten, Löschen eines Mitglieds an duplizieren, Zeitplan, senden, Pause, Lebenslauf, stornieren, Publikum und Empfänger Änderungen, nachdem der Service-Anruf zugesagt hat, nur als id und Verb. - Weder trägt eine Top-Level-KampagneId. Jede Kampagnen-Bildschirm liest einen Rahmen mit einem als Fortschritt und kopiert seine Zähler auf die Zeile, so ein Rahmen eine andere Form, die eine trägt, würde die Zählungen auf Bildschirmen, die noch laufen, ausblenden der ältere Code. Der Absender zählt auch die akzeptierten Nachrichten des Tages pro Charge (stats.daily "sent"), aus dem die zweiwöchigen Funkenlinien des Widgets schöpfen. Die vollständige Suite ist 1534 Tests mit einem Fehler, TransactionalSendRatchetTest, die drei sendToUser Überlastungen seit c47fcf6 zählt und nichts miteinander zu tun hat.
· SecurityService
Das E-Mail Kampagnen Widget kommt für jeden an, der die Kampagnen öffnen kann
EMAIL_CAMPAIGNS_WIDGET und seine ADDED, OPTIONAL und MOVABLE Richtlinien setzen von VIEW_BULK_EMAIL auf dem Boot, der sie einführt, so dass die Pane auf die Startrampe jedes Mitglieds, das die Kampagnen bereits lesen kann, und es ist ihre zu entfernen oder zu bewegen. REQUIRED setzt nicht, wie bei jedem Widget: deploy pins never pins a pane to anybody's home page.
· kamo-shared-library
Die E-Mail-Kampagnen home Widget fünf Rechte
EMAIL_CAMPAIGNS_WIDGET (321) und seine vier Politikkinder (322-325), aufgehängt off VIEW_BULK_EMAIL: jede Lektüre hinter dem Widget, die Kampagnenliste, seine Zähler und die Live-Weruns Frames, nimmt das schon richtig ein, also Widget kann nie ein Weg, es zu umgehen. 326 ist die nächste freie ID.
· kamo-internal
E-Mail-Kampagnen ist der erste Marketing-Tab
Die Registerkarte Marketing Tools liest jetzt E-Mail Kampagnen, Marketing Materialien, Social Media, Tracking Codes. Bulk E-Mail bewegt sich an die Front unter seinem neuen Namen, und Materials nimmt den vollen Namen seine eigene Seite zeigt bereits. Der /marketing Index landet auf der ersten Registerkarte ein Mitglied kann öffnen, so dass seine Reihenfolge bewegt sich mit dem Streifen: E-Mail-Kampagnen standardmäßig, Marketing Materialien für eine Mitglied ohne E-Mail-Recht. Die Route, die Label-Tasten und VIEW_BULK_EMAIL behalten ihre Namen. Die Formulierung ist in Kamo-Translation-Wörterbuch 98a21, zuerst geschoben, mit der zwei Etiketten, die in jedem Ort von Hand geschrieben werden.
· kamo-marketing
Lösungen bewegt sich unter Ressourcen, eine Ebene nach unten
Die obere Reihe trug fünf Kategorien vor der Telefonnummer, die Sprache Selektor und drei CTAs. Lösungen ist jetzt der erste Punkt innerhalb der Ressourcen, über den beiden Artikel Links, und behält seine acht Branchenseiten als Flyout der dritten Ebene. Nichts im Renderer geändert: NavChild trägt schon seine eigene "Kinder", und Legal wurde unter Ressourcen auf diese Weise die ganze Zeit geschachtelt, auf dem Desktop und in der mobilen Akkordeon sowohl. Das sind nur die Daten. "All Industries" bleibt das erste Enkelkind und wird nicht gefaltet in die Elternreihe, weil der mobile Elternteil ein Toggle-Button ist, nicht ein Link - /solutions selbst ist auf einem Telefon ohne sie nicht erreichbar. /solutions Seiten leuchten noch ihre Kategorie auf: isKategorieActive bereits geht die Enkelkinder, so Ressourcen Highlights, wo Lösungen verwendet. Bestätigt auf /en/solutions/real-estate . Ressourcen macht #ffffff auf rgba(107,142,58,0.1) und die anderen vier bleiben #9a9a9a. Verifiziert gegen die laufende Seite, nicht die Quelle. Die obere Reihe liest Features, Dienstleistungen, Preise, Unternehmen, Ressourcen; schwebende Ressourcen dann Lösungen eröffnet die acht Branchen mit ihren /en-Präfixen. Der Flyout ist 200px breit und seine rechte Kante landet bei 1001, 1001, 1076 und 1316 für viewports von 1024 (der lg breakpoint, wo dieses nav überhaupt erscheint), 1280, 1440 und 1920 - im Inneren des Aussichtshafens bei jedem, ohne Horizont Überlauf. Auf einem 390-weiten Telefon Ressourcen öffnet, Solutions öffnet sich unter ihm, und alle acht Links sind da. tsc, check-client-Navigation und check-i18n-Tasten sind sauber.
· kamo-marketing
Anwendungsentwicklung, Webdesign und Webmarketing
************ argumentiert, dass ein Unternehmen eine Agentur bezahlt pro Sitz zahlt für Software, die die Agentur nicht gebaut, gehostet oder behalten hat Laufen. Es endet mit der Frage, wer dieses Geld bekommen sollte und hat noch nie eine Tür zu zeigen. Das ist die Tür. 59 Seiten unter /services: eine Nabe, drei Säulen, 30 Fähigkeitsseiten, 12 Beweisseiten, 5 Vergleiche und sechs darüber, wie ein Engagement tatsächlich läuft. Struktur in TypeScript, Prosa im Wörterbuch - das Muster 37 Branchen, 45 Integrationen und 41 Glossar Begriffe bereits verwenden, so ein Übersetzer kann jeden Satz umschreiben und kann eine Schnecke oder eine Route. Vier neue Kollektionen, die eher auf dem Namensplatz der "Dienste" abgestellt sind als "Kollektionen": Letzteres ist bereits in viele Orte übersetzt und Wiederverwendung würde behaupten, eine französische Service-Seite existiert, bevor ein Wort von das tut es. Heute jede Service-Seite canonicals to English und erscheint in nur die englische Sitemap, das ist, was die Maschinen bereits für eine Seite, deren Kopie nicht übersetzt wurde. Das Portfolio ist unsere eigene Plattform, denn es ist die einzige, die wir lassen können ein Besucher inspizieren: die Mail-Server, die Telefon-Schalter, die WebRTC Medien-Stack, die Namens-Pipeline, das Cluster und diese Website. Jede Zahl auf diesen Seiten trägt den Befehl, von dem sie kam und der Tag es wurde gelesen, und Skripte /check-services.ts verfehlt die Build auf einer Tatsache, dass hat weder - zusammen mit einer Säule Schnecke, dass eine statische / Dienstleistungen Kind würde Schatten, eine baumelnde Beweisreferenz, eine verwaiste Arbeitsseite und ein Vergleich, der keinen Fall gegen sich selbst benennen kann. Diese letzte Regel ist nicht Dekoration: Eine Vergleichsseite, die nicht gegen sich selbst argumentieren kann, ist ein Werbung, die einen Tisch trägt. Die Preisgestaltung veröffentlicht den Mechanismus und nicht eine Tabelle. Wir zitieren nach Entdeckung und beheben Sie die Zahl zuerst; was bewegt es, was nie drin ist (kein Prozentsatz der Werbeausgaben, kein Aufschlag auf alles, was für Sie gekauft wird) und wenn Sie sich herausstellen, sind alle auf /services/how-we-quote. /services/starten postet ein bestehendes Thema bewusst - der Support-Service löst ThemaTitel gegen Themen, die bereits existieren und beantwortet 400 sonst, so ein "Web Design" Thema hätte kompiliert, eingesetzt, richtig aussah, und lehnte jede Vorlage ab. Zwei Barrierefreiheits-Fixes, die nicht streng diese Funktion sind, sondern auf jede Seite davon. globals.css:52 sagt, niemals ein rohes --color-primary* zu verwenden für kleinen Text; das Cookie-Einwilligungsbanner, bei 2.18:1, auf jeder Seite der Website, und RelatedContent tat das gleiche auf Lösungen, Integrationen, Alternativen und Glossar. Beide verwenden nun den lesbaren Akzent, und die Banners Policy-Links sind weiß --color-accent-on-canvas wird berechnet, genau 4.5:1 gegen die Leinwand drücken, die keinen Kopffreiheit für die leicht angehobene Oberfläche das Banner sitzt auf. Alle 19 Service-Seiten, die Homepage, /Preise und /solutionen/* jetzt Pass Achse bei WCAG 2.2 AA mit Null Verstöße; die Gebühren Artikel eigene Table-of-Content-Abzeichen immer noch versagen und werden in Ruhe gelassen.
· kamo-marketing
Ein Artikel über das Zählen Ihrer Software-Abonnements, und das Banner weist darauf hin
/all-in-one-Business-Software fragt, wie viele Abonnements ein Unternehmen bezahlt: eine Checkliste, zählt sie und summiert den Monat und das Jahr, wie der Leser tickt es, was ein Stapel kostet über seine Rechnungen, was all-in-one bedeutet, dass alles wert ist, die Fragen, die man vor der Konsolidierung stellen muss, und wie KamoCRM den gleichen Boden abdeckt. Zwei Außenfiguren, die jeweils in der Kopie genannt und an der Fuß: Zylos SaaS Management Index 2026 über ungenutzte Lizenzen und wer Software-Ausgaben kontrolliert, und Cledara's 2025 Software Spend Report darüber, wie weit Unternehmen ihre Werkzeuganzahl unterschätzen. Die Ankündigung des Banners für den öffentlichen Dienst weist nun eher auf den Artikel auf die Sitzplatz-Gebühr hin. Seine Label ist ein neuer Schlüssel, kein neuer Wert für den alten: Die Wörterbuch-Pipeline überspringt einen Schlüssel, dessen Übersetzung unterscheidet sich bereits von der englischen, so dass jede andere Sprache würde die alte gehalten haben Frage über einen Link zu diesem Artikel. In der Menüzeile Ressourcen, der Ressourcen-Hub und der Sitemap aufgeführt.
· kamo-internal
Die Startrampe Bänder öffnen sich in die Bar eigene Dropdown-Oberfläche
Die Administrator-Bar und die Pinned-App-Bänder sind mit der oberen Bar bemalt Gradient, und dann beantwortet ein Schwebe mit etwas von einer anderen App ganz: ein weiße Tooltip-Karte schwebt zwölf Pixel unter dem Band, und auf einer angehefteten App chip - ein MUI Popover mit grauen Bildunterschriften und keine Naht zu der Sache, aus der es kam. Neun von ihnen, jeder erscheint und verschwindet auf eigene Faust. Falsche Palette, falsch Form, von der falschen Stelle kommen. Sie öffnen sich nun in die SAME-Oberfläche, die die Menüs der oberen Leiste verwenden. Es ist in der Marke der Organisation, seine obere Kante nimmt die genaue Farbe, die das Band an der Stelle hat es geht von, die Filets schweißen es an diesen Rand, und eine Oberfläche gleitet und ändert die Größe von Eintritt zu Eintrag, da der Bezugsgeber die Zeile bereist - so liest sich eine Band als Öffnung und nicht als Karte, die über die Startrampe gelegt wird. • NavTopMenuHost nimmt jedes barähnliche Element, nicht nur NavTop's Header: ein Pro Gastgeber, weil eine Band umgerundete Ecken hat, die Bar nicht, und sowohl das Panel und sein Filet müssen sich mit bemalten Banden treffen. Das Zimmer, das eine Tafel hat um hineinzuwachsen wird gemessen, von wo es tatsächlich beginnt (--kmenu-max-Höhe) anstatt von der Höhe des Navi, was nichts bedeutet, auf halbem Weg nach unten eine Seite. • NavTopMenuPanel gewinnt "kind="note"": die gleiche Fläche und die gleiche Bewegung, Mit Prosa über den Auslöser statt Entscheidungen. Es behauptet, keine Menü-Rolle und nimmt keinen Fokus, so dass die Administrator-Bar Beschreibungen bleiben Beschreibungen und Enter folgt immer noch dem Link, den sie beschreiben. • Der Chip einer gepinnten App zeichnet die Reihen, die das Navi zeichnet (NavToolSectionsPanel, Herausgehoben aus NavToolBarMenu), so antwortet eine Option mit einem Menü, wo auch es wird angeboten - verschachtelte Gruppen, Abzeichen, Filterbox und alle. • Beide Bands lesen ihre Gefälle von navTopSeam.ts. Eine wörtliche Kopie der stops ist genau das, was driftet, und die Naht ist nur unsichtbar, während die Panel und die Band sind sich einig. Tests: die Administrator-Bar gerendert und arbeitete mit einer Maus, einem Finger und der Tastatur (eine Oberfläche, von der Einreise zur Einreise ausgehändigt, nie den Fokus stehlen), plus eine Source Guard, dass keine Band nach einem Popover oder einer zweiten Kopie der greift Gradient wieder.
· kamo-marketing
Einbetten Homepage Marketing-Video auf White-Label CRM-Gebühren Artikel
Geben Sie den Lesern die gleiche Produktrolle von der Homepage nach dem Intro, vor dem Resold-Software-Bereich.
· kamo-shared-library
WebinarNotifyMitglied, die Liste einer Organisation, die
Eine Zeile pro (Organisation, Teammitglied) in webinar_notify_member, erstellt von KamoInitializerService's WebinarNotifyMemberMigration und bereits angemeldet. Die Repository bringt das Teammitglied, da jeder Leser die Person will. Kein fremder Schlüssel, passend zur Migration, also das ddl-auto Update des Initialis fügt nie eine hinzu.
· MediaService
Blind-Kopie die Zusätzlich benachrichtigt Teammitglieder auf Moderator E-Mails
GET/PUT /api/webinar/notify-members (MANAGE_SUPPORT) lesen und ersetzen Organisationsliste Zusätzliche Notified-Liste; jede ID muss ein Teammitglied sein diese Organisation, höchstens 25. WebinarEmailNotifier fügt den Besitz hinzu Die Liste der Organisation als blinde Kopien auf jedem Brief an einen Moderator gebucht, Teilnehmer kamen, Teilnehmer abgesagt, Sitzung abgesagt, Erinnerung - nie auf eine Teilnehmerbrief, nie die eigene Adresse des Moderators, jede Person einmal, und nur Personen, die noch in Frage kommen, angeschrieben zu werden.
· EmailService
Blinde Kopien auf der Service-to-Service-Vorlage senden
SendenTransactionalRequest nimmt eine optionale bcc-Liste, durchgeführt durch sendToUser und auf den SMTP-Umschlag - einschließlich der Plattform-Adresse Retry - so eine kopierte Person bekommt genau die Nachricht, die der Adress adressiert bekommt. blindeCopies trimmt, Drops der Adressperson und Duplikate, und Caps die Liste bei 25. Kein vorhandener Anrufer Änderungen: ohne bcc nimmt der Senden den Weg, den es immer getan hat.
· InitializerService
Webinar_notify_member, die Teammitglieder kopiert auf Moderatoren-E-Mails
Eine Zeile pro (Organisation, Teammitglied): die Zusätzliche Notified Liste auf der Geplante Webinars Einstellungen Registerkarte. MediaService blind-kopiert diese Adressen auf jede Webinar E-Mail an einen Moderator für die Organisation, die die webinar Typ. Eine neue Tabelle, so dass keine Tabelle andere Dienste gelesen wird geändert; keine Zeilen bedeutet, dass niemand kopiert wird. Übertragen auf die Produktion 2026-09-13.
· kamo-internal
Lassen Sie einen Admin wählen, wer auf Moderatoren-E-Mails kopiert wird
Die Registerkarte Webinars erhält einen Abschnitt "Zusätzlich benachrichtigt" die Liste der Webinar-Typen. Die dort ausgewählten Teammitglieder erhalten eine blinde Kopie jede automatisierte E-Mail an einen Moderator (Neubuchung, Teilnehmer beigetreten oder abgesagt, Sitzung abgesagt, Erinnerung) für alle Organisationen Webinare. Es liest und ersetzt die Liste durch /api/webinar/notify-members, pickt Personen mit dem gleichen multi-selektierten Verzeichnis-Picker, den die Presenters-Tab verwendet, und speichert explizit mit einem unrettierten Wechsel-Hinweis und einer gespeicherten Bestätigung. Ein 403 verbirgt den Abschnitt, eine defehlgeschlagene Ladung bietet eine Wiederholung statt einer leeren Liste, ein abgelehntes Speicher zeigt den Grund des Servers, und die Änderung eines anderen Admins kommt live über das Webinar org-change Thema.
· kamo-shared-library
Canonische Vorlagen für jeden Webinar Buchungsbrief
Sieben meet.webinar_* Vorlagen - der Moderator gebucht / Teilnehmer beigetreten / Teilnehmer stornierten Mitteilungen, die Bestätigung und Absage des Teilnehmers, Sitzungsstorniertes Brief und die geplante Erinnerung - registriert in CANONICAL_KEYS, mit WebinarEmail, der die eine variable Karte erstellt, die sie ausfüllt: Zeiten in der Leserzone, antwortet das Formular des Buchers für den Moderator, Gäste verbinden Link und persönlichen Abbruch Link für Teilnehmer, die Konsole Link für die Moderator, und Blöcke, die zusammenbrechen, wenn es nichts zu zeigen.
· kamo-marketing
Lassen Sie einen Besucher ihre Registrierung von der E-Mail-Link stornieren
/webinar/cancel/<token" ist, wo eine Webinar-Bestätigung E-Mail jemanden sendet der es nicht mehr schafft. Es sieht die Registrierung durch die Öffentlichkeit webinar API, zeigt das Webinar, Moderator, Datum und Uhrzeit (in der Besucher eigene Locale und Zeitzone, mit der Zone benannt) und Länge, und löscht es hinter einem Bestätigungsschritt. Ein unbekannter Link, eine bereits annullierte Anmeldung und ein Webinar, das bereits gehalten wurde jeder bekommen ihren eigenen Staat, und ein Ablehnung der API wird als API-Wörter angezeigt. noindex/nofollow, und nicht in der Sitemap: der Pfad ist dynamisch, so dass die Sitemap Walker überspringt es und nichts generiert Einträge für sie. Copy lebt in der neue webinarCancel namespace.
· KlusterServices
Feedback-ID in DKIM-Signaturen unterschreiben
Gmail zählt eine Kampagnen-Nachricht in Richtung seiner Feedback-Loop nur, wenn die Feedback-ID-Header ist gedeckt durch die DKIM-Signatur der sendenden Domain. local.d/dkim.conf hält rspamd's default signiert Header und fügt Feedback-id.

Euer Universum wartet.
Fügen Sie Produkte hinzu, wann immer Sie möchten – keine Migration, keine neuen Anmeldungen.
Für immer kostenlos – keine Kreditkarte erforderlich