Skip to content

Slack: inbound <mailto:…|label> and <tel:…|label> links are not converted, so the label ends up inside the link URL #955

Description

@szachariah-tl

Bug Description

slackMrkdwnToMarkdown converts Slack link tokens only when the target starts with http:// or https://. Slack uses the same <target|label> token for mailto: and tel: links, and it auto-links every email address a user types, so ordinary messages contain <mailto:a@b.com|a@b.com>.

The token passes through the converter unchanged. parseMarkdown then reads <mailto:a@b.com|a@b.com> as a CommonMark autolink, which produces a link node whose url is mailto:a@b.com|a@b.com. message.text contains mailto:a@b.com|a@b.com, and stringifyMarkdown(message.formatted) emits the raw Slack token.

Steps to Reproduce

  1. In Slack, send the bot a message that contains an email address, for example mail a@b.com please. Slack delivers text: "mail <mailto:a@b.com|a@b.com> please".
  2. Read message.text and stringifyMarkdown(message.formatted) in the handler, or run the code sample below, which calls the same converter the adapter uses.

Expected Behavior

A link node with url: "mailto:a@b.com" and text a@b.com, the same treatment <https://…|label> gets. message.text is mail a@b.com please. The same applies to <tel:+15551234567|555-123-4567> and to the unlabelled forms <mailto:a@b.com> and <tel:+15551234567>.

Actual Behavior

Input (event.text) link.url message.text stringifyMarkdown
mail <mailto:a@b.com|a@b.com> please mailto:a@b.com|a@b.com mail mailto:a@b.com|a@b.com please mail <mailto:a@b.com|a@b.com> please
call <tel:+15551234567|555-123-4567> now tel:+15551234567|555-123-4567 call tel:+15551234567|555-123-4567 now call <tel:+15551234567|555-123-4567> now
mail <mailto:a@b.com> please mailto:a@b.com mail mailto:a@b.com please mail <mailto:a@b.com> please

In the unlabelled case the URL is correct, but the visible text and message.text include the mailto: scheme.

Code Sample

import { SlackFormatConverter } from "@chat-adapter/slack";
import { stringifyMarkdown, toPlainText } from "chat";

const ast = new SlackFormatConverter().toAst("mail <mailto:a@b.com|a@b.com> please");
console.log(toPlainText(ast));        // "mail mailto:a@b.com|a@b.com please"
console.log(stringifyMarkdown(ast));  // "mail <mailto:a@b.com|a@b.com> please\n"

Chat SDK Version

4.30.0

Node.js Version

22.21.1

Platform Adapter

Microsoft Teams, Slack

Operating System

Linux

Additional Context

Workaround we run, applied to the mrkdwn before the converter in a SlackFormatConverter subclass:

const LABELLED_ADDRESS_LINK = /<((?:mailto|tel):[^|<>]+)\|([^<>]+)>/g;
const BARE_ADDRESS_LINK = /<((?:mailto|tel):([^|<>]+))>/g;

export function normalizeSlackMrkdwn(mrkdwn: string): string {
  return mrkdwn.replace(LABELLED_ADDRESS_LINK, "[$2]($1)").replace(BARE_ADDRESS_LINK, "[$2]($1)");
}

export class NormalizingSlackFormatConverter extends SlackFormatConverter {
  override toAst(mrkdwn: string): Root {
    return super.toAst(normalizeSlackMrkdwn(mrkdwn));
  }
}

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions